]> Creatis software - bbtk.git/blob - kernel/src/bbtkInterpreter.cxx
dac3e047189dcffc96a91b60d1fb2c2f54f2523a
[bbtk.git] / kernel / src / bbtkInterpreter.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   bbtk
4   Module:    $RCSfile: bbtkInterpreter.cxx,v $ $
5   Language:  C++
6   Date:      $Date: 2008/01/30 09:28:15 $
7   Version:   $Revision: 1.15 $
8                                                                                 
9   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10   l'Image). All rights reserved. See Doc/License.txt or
11   http://www.creatis.insa-lyon.fr/Public/bbtk/License.html for details.
12
13      This software is distributed WITHOUT ANY WARRANTY; without even
14      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15      PURPOSE.  See the above copyright notices for more information.
16                                                                                 
17 =========================================================================*/
18 /**
19  *  \file 
20  *  \brief class Interpreter : 
21  */
22
23 #include "bbtkInterpreter.h" 
24 #include "bbtkMessageManager.h"
25 #include "bbtkConfigurationFile.h"
26 #include "bbtkWxConsole.h"
27 #include "bbtkUtilities.h"
28 #include <sys/stat.h>
29 #ifdef CMAKE_HAVE_TERMIOS_H
30 #include <termios.h>
31 #define BBTK_USE_TERMIOS_BASED_PROMPT
32 #endif
33
34 #include <string>
35
36 namespace bbtk
37 {
38
39 Interpreter* Interpreter::mGlobalInterpreter = NULL;
40
41  //=======================================================================
42  /**
43    *  
44    */
45   Interpreter::Interpreter() 
46     :
47     mCommandLine(false), verbose(false)
48   {
49     bbtk::MessageManager::RegisterMessageType("Echo","Level>0 : Prints the 'echo' commands of the user.\n\tLevel>1 : Prints the command being interpreted",1);
50     bbtk::MessageManager::RegisterMessageType("Interpreter","Messages of the interpreter",0);
51     bbtkDebugMessageInc("Interpreter",9,"Interpreter::Interpreter()" <<std::endl);
52  
53     mGlobalInterpreter = this;
54
55     //    mFactory = new bbtk::Factory();
56     mExecuter = new bbtk::Executer();
57     //mExecuter->SetFactory(mFactory);
58
59     // Builds the commands dict
60     CommandInfoType info;
61    
62     info.keyword = "new";
63     info.argmin = 2;
64     info.argmax = 2;
65     info.code = cNew;
66     info.syntax = "new <type> <name>";
67     info.help = "Creates a new black box of type <type> with name <name>";
68     mCommandDict[info.keyword] = info;
69     
70     info.keyword = "delete";
71     info.argmin = 1;
72     info.argmax = 1;
73     info.code = cDelete;
74     info.syntax = "delete <box>";
75     info.help = "Deletes the black box of name <box>";
76     mCommandDict[info.keyword] = info;
77
78     info.keyword = "connect";
79     info.argmin = 2;
80     info.argmax = 2;
81     info.code = cConnect;
82     info.syntax = "connect <box1.output> <box2.input>";
83     info.help = "Connects the ouput <output> of black box <box1> to the input <input> of black box <box2>";
84     mCommandDict[info.keyword] = info;
85
86     info.keyword = "print";
87     info.argmin = 1;
88     info.argmax = 1;
89     info.code = cPrint;
90     info.syntax = "print <string>";
91     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').";
92     mCommandDict[info.keyword] = info;
93
94     info.keyword = "exec";
95     info.argmin = 1;
96     info.argmax = 2;
97     info.code = cExec;
98     info.syntax = "exec <box | 'freeze' | 'unfreeze' >";
99     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.";
100     mCommandDict[info.keyword] = info;
101
102     info.keyword = "package";
103     info.argmin = 1;
104     info.argmax = 1;
105     info.code = cPackage;
106     info.syntax = "package <name>";
107     info.help = "Begins the definition of a package.";
108     mCommandDict[info.keyword] = info;
109     
110     info.keyword = "endpackage";
111     info.argmin = 0;
112     info.argmax = 0;
113     info.code = cEndPackage;
114     info.syntax = "endpackage";
115     info.help = "Ends the definition of a package.";
116     mCommandDict[info.keyword] = info;
117
118     info.keyword = "define";
119     info.argmin = 1;
120     info.argmax = 2;
121     info.code = cDefine;
122     info.syntax = "define <type> [<package>]";
123     info.help = "Begins the definition of a new type of complex black box called <type>. If <package> if provided will create it in the given package.";
124     mCommandDict[info.keyword] = info;
125     
126     info.keyword = "endefine";
127     info.argmin = 0;
128     info.argmax = 0;
129     info.code = cEndDefine;
130     info.syntax = "endefine";
131     info.help = "Ends the definition of a new type of complex black box";
132     mCommandDict[info.keyword] = info;
133
134     info.keyword = "input";
135     info.argmin = 3;
136     info.argmax = 3;
137     info.code = cInput;
138     info.syntax = "input <name> <box.input> <help>";
139     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";
140     mCommandDict[info.keyword] = info;
141
142     info.keyword = "output";
143     info.argmin = 3;
144     info.argmax = 3;
145     info.code = cOutput;
146     info.syntax = "output <name> <box.output> <help>";
147     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";
148     mCommandDict[info.keyword] = info;
149
150     info.keyword = "set";
151     info.argmin = 2;
152     info.argmax = 2;
153     info.code = cSet;
154     info.syntax = "set <box.input> <value>";
155     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";
156     mCommandDict[info.keyword] = info;
157    
158     info.keyword = "config";  // JPR
159     info.argmin = 0;
160     info.argmax = 1;
161     info.code = cConfig;
162     info.syntax = "config [<verbose>|<v>]";
163     info.help = "Prints the value of all configuration parameters";
164     mCommandDict[info.keyword] = info;
165
166     info.keyword = "reset";  //EED
167     info.argmin = 0;
168     info.argmax = 0;
169     info.code = cReset;
170     info.syntax = "reset";
171     info.help = "Deletes all boxes and unloads all packages (bbi is reset to its start state)";
172     mCommandDict[info.keyword] = info;
173
174     info.keyword = "author";
175     info.argmin = 1;
176     info.argmax = 1;
177     info.code = cAuthor;
178     info.syntax = "author <string>";
179     info.help = "Adds the string <string> to the author information of the black box being defined";
180     mCommandDict[info.keyword] = info;
181     
182     info.keyword = "keyword"; //JP
183     info.argmin = 1;
184     info.argmax = 1;
185     info.code = cKeyword;
186     info.syntax = "keyword <list of items, separated by ;>";
187     info.help = "Adds the string <string> to the keyword information of the black box being defined";
188     mCommandDict[info.keyword] = info;
189
190     info.keyword = "description";
191     info.argmin = 1;
192     info.argmax = 1;
193     info.code = cDescription;
194     info.syntax = "description <string>";
195     info.help = "Adds the string <string> to the descriptive information of the black box being defined";
196     mCommandDict[info.keyword] = info;
197
198     info.keyword = "help";
199     info.argmin = 0;
200     info.argmax = 2;
201     info.code = cHelp;
202     info.syntax = "help";
203     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>";
204     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.";
205     mCommandDict[info.keyword] = info;
206
207     info.keyword = "message";
208     info.argmin = 0;
209     info.argmax = 2;
210     info.code = cMessage;
211     info.syntax = "message <category> <level>";
212     info.help = "Sets the level of the category of messages <category> to <level>.\n  If category='All' then sets the level for all categories. If no category nor level is passed then prints info on available categories of messages and their current level.";
213     mCommandDict[info.keyword] = info;
214
215     info.keyword = "include";
216     info.argmin = 1;
217     info.argmax = 1;
218     info.code = cInclude;
219     info.syntax = "include <filename>";
220     info.help = "Includes the file <filename>";
221     mCommandDict[info.keyword] = info;
222
223     info.keyword = "quit";
224     info.argmin = 0;
225     info.argmax = 0;
226     info.code = cQuit;
227     info.syntax = "quit";
228     info.help = "Quits the program (during script execution it stops the complete execution)";
229     mCommandDict[info.keyword] = info;
230
231     info.keyword = "load";
232     info.argmin = 1;
233     info.argmax = 1;
234     info.code = cLoad;
235     info.syntax = "load <packagename>";
236     info.help = "Loads the black box package <packagename>";
237     mCommandDict[info.keyword] = info;
238
239     info.keyword = "unload";
240     info.argmin = 1;
241     info.argmax = 1;
242     info.code = cUnload;
243     info.syntax = "unload <packagename>";
244     info.help = "Unloads the black box package <packagename>";
245     mCommandDict[info.keyword] = info;
246
247     info.keyword = "graph";
248     info.argmin = 0;
249     info.argmax = 6;
250     info.code = cGraph;
251     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 ]]]]]]";
252     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')";
253     mCommandDict[info.keyword] = info;
254
255     /*
256     info.keyword = "workspace";
257     info.argmin = 1;
258     info.argmax = 2;
259     info.code = cWorkspace;
260     info.syntax = "workspace < ( freeze | unfreeze ) | ( rename <newname> ) >";
261     info.help = "Configures the workspace.\n        'freeze' allow 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.";
262     mCommandDict[info.keyword] = info;
263     */
264
265     bbtkDebugDecTab("Interpreter",9);
266
267   } 
268   //=======================================================================
269   
270   
271   
272   //=======================================================================  
273   /**
274    *  
275    */
276   Interpreter::~Interpreter()
277   {
278     bbtkDebugMessageInc("Interpreter",9,"Interpreter::~Interpreter()" <<std::endl);
279     delete mExecuter;
280     //delete mFactory;
281
282     //    std::cout <<"EO Interpreter::~Interpreter()"<<std::endl;
283     bbtkDebugDecTab("Interpreter",9);
284   }
285   //=======================================================================
286
287
288   //=======================================================================
289   /**
290    *  
291    */
292   void Interpreter::InterpretFile( const std::string& filename,  bool use_configuration_file, bool verbose)
293   {
294     bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
295
296     bool exm = mCommandLine;
297     mCommandLine = false;
298
299     try 
300     {
301       SwitchToFile(filename, use_configuration_file, verbose);
302       bool insideComment = false; // for multiline comment
303       while (mFile.size()>0) 
304       {
305          while ((mFile.size()>0) && 
306                 (!mFile.back()->eof()))
307          {
308             mLine.back()++;
309             char buf[500];
310             mFile.back()->getline(buf,500);
311       
312             std::string str(buf);
313             int size=str.length();
314             if ( str[ size-1 ]==13  )
315             {
316                str.erase(size-1,1);
317             }
318       
319             InterpretLine(str, insideComment);
320          }
321         //if (mFile.size()>0) 
322         CloseCurrentFile();
323       }
324     }
325     catch (QuitException e) 
326     {
327     }
328     catch (bbtk::Exception e) 
329     {
330       std::cerr << "* ERROR : "<<e.GetMessage()<<std::endl;
331       if (mFileName.size()) {
332          std::cerr << "* FILE  : \""<<mFileName.back()<<"\""<<std::endl;
333          std::cerr << "* LINE  : "<<mLine.back()<<std::endl;
334       }    
335     }
336     catch (std::exception& e) 
337     {
338        std::cerr << "* ERROR : "<<e.what()<<" (not in bbtk)"<<std::endl;
339        if (mFileName.size()) {
340           std::cerr << "* FILE  : \""<<mFileName.back()<<"\""<<std::endl;
341           std::cerr << "* LINE  : "<<mLine.back()<<std::endl;
342        }    
343     }  
344     catch (...)
345     {
346        std::cout << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
347        if (mFileName.size()) {
348           std::cout << "* FILE  : \""<<mFileName.back()<<"\""<<std::endl;
349           std::cout << "* LINE  : "<<mLine.back()<<std::endl;
350       }    
351     }
352
353     CloseAllFiles();
354     bbtkDebugMessage("Interpreter",9,"EO Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
355     bbtkDecTab("Interpreter",9);
356
357     mCommandLine = exm;
358   }
359   //=======================================================================
360
361
362
363   //=======================================================================  
364   /**
365    *
366    */
367 void Interpreter::InterpretLine( const std::string& line, bool &insideComment )
368 {
369
370     bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretLine(\""<<line<<"\")"<<std::endl);
371     bbtkMessage("Echo",2,"\""<<line<<"\""<<std::endl);
372
373     std::vector<std::string> words;
374     SplitLine(line,words);
375
376     // Empty line
377     if (words.size()<1) 
378     {
379        bbtkDebugDecTab("Interpreter",9);
380        return;
381     }
382
383     // Single line comment : # or //
384     if ( words[0][0]=='#' || (words[0][0]=='/' && words[0][1]=='/') ) 
385     {  
386        bbtkDebugDecTab("Interpreter",9);
387        bbtkMessage("Interpreter",9,"Comment"<<std::endl);
388        return;
389     }
390
391     // Multi line comment ( /* ... */ ) -delimiters on different lines !-
392     
393     if (words[0][0]=='/' && words[0][1]=='*') 
394     {  
395        bbtkDebugDecTab("Interpreter",9);
396        bbtkMessage("Interpreter",9,"In multiline comment"<<std::endl);
397        insideComment = true;
398        return;
399     }
400
401     if (words[0][0]=='*' && words[0][1]=='/') 
402     {  
403        bbtkDebugDecTab("Interpreter",9);
404        bbtkMessage("Interpreter",9,"Out multiline comment"<<std::endl);
405        if ( !insideComment ) {
406           bbtkDebugDecTab("Interpreter",9);
407           bbtkMessage("Interpreter",9,"Comment mismatch : '*/' with no matching '/*'"<<std::endl);       
408        }
409        insideComment = false;
410        return;
411     }
412
413     if (insideComment) 
414     {  
415        bbtkDebugDecTab("Interpreter",9);
416        bbtkMessage("Interpreter",9,"Multiline Comment"<<std::endl);
417        return;
418     }
419
420     // Command 
421     CommandInfoType command;
422     InterpretCommand(words,command);
423
424     bbtkDebugMessage("Interpreter",9,
425                      "Command='"<<command.keyword
426                       <<"' code="<<command.code<<std::endl); 
427     int level=0;
428     std::string left,right,left2,right2;
429     std::string filename;
430     switch (command.code) 
431     {
432       case cNew :
433         mExecuter->Create(words[1],words[2]);
434         break;
435         
436       case cDelete :
437         // TO DO !!
438         // mExecuter->Remove(words[1]);
439         break;
440         
441       case cConnect :
442         Utilities::SplitAroundFirstDot(words[1],left,right);
443         Utilities::SplitAroundFirstDot(words[2],left2,right2);      
444         mExecuter->Connect(left,right,left2,right2);
445         break;
446         
447       case cPackage :
448         mExecuter->BeginPackage(words[1]);
449         break;
450
451       case cEndPackage :
452         mExecuter->EndPackage();
453         break;
454         
455       case cDefine :
456         if (mFileName.size()>0) 
457         {
458            filename = Utilities::get_file_name(mFileName.back());
459         }
460         if (words.size()==2) 
461         {
462            mExecuter->Define(words[1],"",filename);
463         }
464         else 
465         {
466            mExecuter->Define(words[1],words[2],filename);
467         }
468         break;
469         
470       case cEndDefine :
471         mExecuter->EndDefine();
472         break;
473         
474       case cPrint :
475         Print(words[1]); /// \todo use mExecuter 
476         break;
477         
478       case cExec :
479         if (words[1]=="freeze") 
480           mExecuter->SetNoExecMode(true);
481         else if (words[1]=="unfreeze") 
482           mExecuter->SetNoExecMode(false);
483         else 
484           mExecuter->Update(words[1]);
485         break;
486         
487       case cInput :
488         Utilities::SplitAroundFirstDot(words[2],left,right);
489         mExecuter->DefineInput(words[1],left,right,words[3]);
490         break;
491         
492       case cOutput :
493         Utilities::SplitAroundFirstDot(words[2],left,right);
494         mExecuter->DefineOutput(words[1],left,right,words[3]);
495         break;
496         
497       case cSet :
498         Utilities::SplitAroundFirstDot(words[1],left,right);
499         mExecuter->Set(left,right,words[2]);
500         break;
501         
502       case cAuthor :
503         mExecuter->Author(words[1]);
504         break;
505
506       case cKeyword :
507         mExecuter->Keyword(words[1]);
508         break;
509                 
510       case cDescription :
511         mExecuter->Description(words[1]);
512         break;
513         
514       case cHelp :
515         Help(words);
516         break;
517         
518       case cMessage : 
519         if (words.size()<3) 
520         {
521             bbtk::MessageManager::PrintInfo();
522         }
523         else 
524         {
525            sscanf(words[2].c_str(),"%d",&level);
526            bbtk::MessageManager::SetMessageLevel(words[1],level);
527         }
528         break;
529         
530       case cGraph : 
531         Graph(words);
532         break;
533         
534       case cConfig :
535         if (words.size()>1) // any param for config means verbose = true
536           verbose = true;
537         else
538           verbose = false;
539         Config(verbose);            
540         break;
541         
542       case cReset :  // EED
543         this->mExecuter->Reset();
544         break;
545         
546       case cInclude :
547         if (mCommandLine) 
548         {
549            InterpretFile(words[1], true, verbose); // true : better pass use_config_file
550         }
551         else 
552         {
553             SwitchToFile(words[1], true, verbose); // true : better pass use_config_file
554         }
555         break;
556         
557       case cLoad:
558         LoadPackage(words[1], true, verbose); // true : better pass use_config_file
559         break;
560         
561       case cUnload:
562         UnLoadPackage(words[1]);
563         break;
564         
565       case cQuit :
566         throw QuitException();
567         break;
568         
569          case cWorkspace :
570         if (words.size() == 2) 
571         {
572            if (words[1]=="freeze")        mExecuter->SetNoExecMode(true);
573            else if (words[1]=="unfreeze") mExecuter->SetNoExecMode(false);
574         }
575         else 
576         {
577            mExecuter->SetWorkspaceName(words[2]);
578         }
579         break;
580         
581       default:
582         bbtkInternalError("should not reach here !!!");
583    }
584     
585    bbtkDecTab("Interpreter",9);
586 }
587   //=======================================================================  
588
589
590
591   //=======================================================================
592   void SplitString ( const std::string& str, const std::string& delimiters, 
593                      std::vector<std::string>& tokens)
594   {
595     // Skip delimiters at beginning.
596     std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
597     // Find first delimiter.
598     std::string::size_type pos     = str.find_first_of(delimiters, lastPos);
599     
600     while (std::string::npos != pos || std::string::npos != lastPos)
601       {
602         // Found a token, add it to the vector.
603         tokens.push_back(str.substr(lastPos, pos - lastPos));
604         // Skip delimiters.  Note the "not_of"
605         lastPos = str.find_first_not_of(delimiters, pos);
606         // Find next delimiter
607         pos = str.find_first_of(delimiters, lastPos);
608       }
609     
610   }
611   //=======================================================================
612
613
614
615   //=======================================================================
616   /**
617    *  
618    */
619 void Interpreter::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
620 {
621     bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
622  
623     std::string delimiters = "\"";
624     std::vector<std::string> quote;
625     SplitString(str,delimiters,quote);
626
627     delimiters = " \t";
628     std::vector<std::string>::iterator i;
629     for (i=quote.begin(); i!=quote.end(); ) 
630     {
631        SplitString(*i,delimiters,tokens);
632        ++i;
633        if (i!=quote.end()) 
634        {
635         //    bbtkDebugMessage("Interpreter",0,"\""<<*i<<"\""<<std::endl);
636           tokens.push_back(*i);
637           ++i;
638        }
639     }
640
641     for (i=tokens.begin(); i!=tokens.end(); ++i) 
642     {
643        bbtkDebugMessage("Interpreter",9,"["<<*i<<"] ");
644     }
645     bbtkDebugMessageCont("Interpreter",9,std::endl);
646
647     bbtkDebugDecTab("Interpreter",9);    
648  }
649   //=======================================================================
650
651
652   //=======================================================================
653   // Replaces substrings "\\n" by a real carriage return "\n"
654   void SubsBackslashN ( std::string& s )
655   {
656     //   std::cout << "BEFORE=["<<s<<"]"<<std::endl;
657     std::string ss("\\n");
658     std::string::size_type pos = 0;
659     pos = s.find(ss,0);
660     char* cr = "\n";
661     while ( pos != std::string::npos )
662    {
663       //  std::cout << "*** find one "<<std::endl;
664       s.replace(pos,2,cr,1);
665       pos = s.find(ss, pos-1);
666    } 
667     //    std::cout << "AFTER=["<<s<<"]"<<std::endl;
668   }
669   //=======================================================================
670
671
672   //=======================================================================
673   /**
674    *  
675    */
676   void Interpreter::Print( const std::string& str)
677   {
678     if (mExecuter->GetNoExecMode()) return;
679
680     bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
681
682     std::vector<std::string> chains;
683     std::string delimiters("$");
684
685     // Skip delimiters at beginning.
686     std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
687     bool is_text = true;
688     if (lastPos>0) is_text = false;
689   
690     // Find first delimiter.
691     std::string::size_type pos     = str.find_first_of(delimiters, lastPos);
692     
693     while (std::string::npos != pos || std::string::npos != lastPos)
694     {
695        if (is_text) 
696        {
697           // Found a text token, add it to the vector.
698           chains.push_back(str.substr(lastPos, pos - lastPos));
699           // std::cout << "text='"<<chains.back()<<"'"<<std::endl;
700        }
701        else 
702        {
703        // is an output (between $$) : decode 
704          std::string tok,box,output;
705          tok = str.substr(lastPos, pos - lastPos);
706          Utilities::SplitAroundFirstDot(tok,box,output);
707          chains.push_back( mExecuter->Get(box,output) );
708     //    std::cout << "outp='"<<chains.back()<<"'"<<std::endl;
709        }
710         // Skip delimiters.  Note the "not_of"
711        lastPos = str.find_first_not_of(delimiters, pos);
712         // Find next delimiter
713        pos = str.find_first_of(delimiters, lastPos);
714     //
715        is_text = !is_text;
716      }
717     //    std::cout << "nb="<<chains.size()<<std::endl;
718      std::vector<std::string>::iterator i;
719      for (i= chains.begin(); i!=chains.end(); ++i) 
720      {
721        //  bbtkMessage("Echo",1,*i);
722        SubsBackslashN(*i);
723        std::cout << *i;
724      }
725      std::cout << std::endl;
726      bbtkDebugDecTab("Interpreter",9);    
727  }
728
729   //=======================================================================
730   /**
731    *  
732    */
733
734 // ===================================================================================
735
736   void Interpreter::SwitchToFile( const std::string& name,
737                                   bool use_configuration_file, bool verbose)
738   {
739   // Note : in the following :
740   // name : the user supplied name 
741   //      - abreviated name    e.g.       scr   scr.bbs
742   //      - relative full name e.g.       ./scr.bbs   ../../scr.bbs 
743   //      - absolute full name e.g.       /home/usrname/proj/dir/scr.bbs
744   //          same for Windows, with      c:, d: ...
745   //
746   // expression like directory/subdir/scrname.bbs is FORBIDDEN (*)
747   // use ./directory/subdir/scrname.bbs
748   //
749   //   (*) except when using packagename/boxes/*
750   
751     bbtkDebugMessageInc("Interpreter",9,"Interpreter::SwitchToFile( \""
752                          <<name<<"\")"<<std::endl);
753
754 // to be remove in final version
755 // use : Config v
756 //verbose = true;
757     std::vector<std::string> script_paths;
758     std::string fullPathScriptName;  // full path script name
759     std::string pkgname;             // e.g. <scriptname>.bbs
760
761     if (use_configuration_file)
762     {
763         // The following is *NOT* a debug time message :
764         // It's a user intended message.
765         // Please don't remove it.
766       if (verbose)
767          std::cout << "look for : [" << name << "] (use_configuration_file == TRUE)"  << std::endl;
768       script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
769     }
770     std::string upath;
771     pkgname = Utilities::ExtractScriptName(name,upath);
772     
773     bool fullnameGiven = false; 
774     bool foundFile     = false;
775
776     if(pkgname == "*") // =========================================== load all boxes (e.g. std/boxes/*)
777     {
778       std::string path;
779       std::vector<std::string>::iterator i;
780       std::string fullDirectoryName;
781       for (i=script_paths.begin();i!=script_paths.end();++i)
782       {
783         path = *i;
784
785        // we *really* want '.' to be the current working directory
786         if (path == ".") {
787           char buf[2048]; // for getcwd
788           char * currentDir = getcwd(buf, 2048);
789           std::string cwd(currentDir);
790           path = currentDir;
791         }
792
793         fullDirectoryName = Utilities::MakePkgnameFromPath(path, upath, false);
794 //std::cout <<"fullpath [" <<   fullDirectoryName << "]" <<std::endl;
795       // Check if library exists           
796         if ( ! Utilities::IsDirectory(fullDirectoryName) )
797         {
798         // The following is *NOT* a debug time message :
799         // It's a user intended message.
800         // Please don't remove it.
801           if (verbose)
802             std::cout <<"   [" <<fullDirectoryName <<"] : doesn't exist" <<std::endl;
803           continue;  // try next path
804         }
805         foundFile = true;
806
807         std::vector<std::string> Filenames;
808         int nbFiles = Utilities::Explore(fullDirectoryName, false, Filenames);
809 // std::cout << "=================nbFiles " << nbFiles << std::endl;
810         int nbBssFiles = 0;
811         for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
812         {
813            if ((*i).substr((*i).size()-4, 4) != ".bbs")
814               continue;      // ignore non .bbs files
815            LoadScript(*i);
816            nbBssFiles++;
817         }
818         if (nbBssFiles==0)
819            if (verbose)
820               std::cout << "WARNING : No '.bbs' file found in [" << fullDirectoryName << "]" << std::endl;
821            
822         break; // a directory was found; we stop iterating
823        }
824        return;
825     }
826
827     std::string::size_type slash_position = name.find_last_of("/\\");
828
829     // if name starts with a / or a . or contains : user is assumed to have passed a relative/absolute name
830     // (not only a plain script name)
831     // we trust him, and try to expland the directory name
832     // WARNING : starting from current local directory :  ./whatYouWant  (./ mandatory!)
833
834     if (name[0]=='/' || name[1] == ':' || name[0]=='.')  // absolute path (linux/windows) or relative path
835     { 
836
837       // ===========================================================check user supplied location
838       fullnameGiven = true;
839
840       fullPathScriptName =  Utilities::ExpandLibName(name, verbose);
841
842       // allow user to always forget ".bbs"
843       int l = fullPathScriptName.size();
844
845       if (l!=0) {
846       
847       if (l>4)
848       {
849          if (fullPathScriptName.substr(l-4, 4) != ".bbs")
850          {
851             fullPathScriptName = fullPathScriptName + ".bbs";
852          }
853       }
854       else
855       {
856          fullPathScriptName = fullPathScriptName + ".bbs";   
857       }
858
859         if ( Utilities::FileExists(fullPathScriptName))
860         {
861           foundFile = true;
862         }
863       } // endif l != 0
864     }
865     else 
866
867       // =============================================================== iterate on the paths
868       {
869       std::string path;
870       std::vector<std::string>::iterator i;
871       for (i=script_paths.begin();i!=script_paths.end();++i)
872       {
873
874         path = *i;
875        // we *really* want '.' to be the current working directory
876         if (path == ".") {
877           char buf[2048]; // for getcwd
878           char * currentDir = getcwd(buf, 2048);
879           std::string cwd(currentDir);
880           path = currentDir;
881         }
882
883        // fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true); //pkgname);
884
885             fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true);
886 //std::cout << "FULL PATH = "<<fullPathScriptName<<std::endl;
887
888       // Check if library exists
889         if ( ! Utilities::FileExists(fullPathScriptName) )
890         {
891         // The following is *NOT* a debug time message :
892         // It's a user intended message.
893         // Please don't remove it.
894           if (verbose)
895             std::cout <<"   [" <<fullPathScriptName <<"] : doesn't exist" <<std::endl;
896           continue;  // try next path
897         }
898         if (verbose)
899            std::cout <<"   [" <<fullPathScriptName <<"] : found" <<std::endl;        
900         foundFile = true;
901         break; // a script was found; we stop iterating
902
903       } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
904     }
905
906     if (!foundFile)
907     {
908        if (fullnameGiven)
909          if(fullPathScriptName == "")
910             bbtkError("Path ["<<upath<<"] doesn't exist");
911          else
912             bbtkError("Script ["<<fullPathScriptName<<"] not found");
913        else
914           bbtkError("No ["<<pkgname<<".bbs] script found");
915        return;    
916     }
917     else
918        LoadScript(fullPathScriptName);
919
920     return;
921   }   
922    
923
924   //=======================================================================
925
926   void Interpreter::LoadScript( std::string fullPathScriptName)
927   {
928     bbtkMessage("Interpreter",1,fullPathScriptName<<" found"<<std::endl);
929
930     std::ifstream* s;      
931     s = new std::ifstream;
932     s->open(fullPathScriptName.c_str());
933     if (!s->good()) 
934     {
935         bbtkError("Could not open file ["<<fullPathScriptName<<"]");
936         return;     
937     }
938     
939     if (verbose)
940        std::cout << "   -->[" << fullPathScriptName << "] found" << std::endl;
941
942     mFile.push_back(s);
943     mFileName.push_back(fullPathScriptName);
944     mLine.push_back(0);
945     return;  
946   }
947
948   //=======================================================================
949   /**
950    *  
951    */
952   void Interpreter::CloseCurrentFile()
953   {
954     bbtkDebugMessage("Interpreter",9,"Interpreter::CloseCurrentFile()"
955                       <<std::endl);
956     
957     if (mFile.size()==0) 
958     {
959       bbtkDebugMessage("Interpreter",9," -> no file left open"<<std::endl);
960       return;
961     }
962
963     mFile.back()->close();
964     delete mFile.back();
965     mFile.pop_back();
966     bbtkDebugMessage("Interpreter",9,
967                      " Closing file '"<<mFileName.back()<<"'"<<std::endl);
968     
969     mFileName.pop_back();
970     mLine.pop_back();
971     bbtkDebugMessage("Interpreter",9," Remains "
972                      <<mFile.size()
973                      <<" open"<<std::endl);
974     bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseCurrentFile()"
975                      <<std::endl);
976   }
977   //=======================================================================
978
979  //=======================================================================
980   /**
981    *  
982    */
983   void Interpreter::CloseAllFiles()
984   {
985     bbtkDebugMessage("Interpreter",9,"Interpreter::CloseAllFiles()"
986                       <<std::endl);
987     
988     while (mFile.size() != 0) 
989     {
990       mFile.back()->close();
991       delete mFile.back();
992       mFile.pop_back();
993       bbtkDebugMessage("Interpreter",9,
994                       " Closing file '"<<mFileName.back()<<"'"<<std::endl);
995       mFileName.pop_back();
996       mLine.pop_back();
997     }
998     bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseAllFiles()"
999                       <<std::endl);
1000   }
1001   //=======================================================================
1002
1003
1004
1005   //=======================================================================
1006   /**
1007    *  
1008    */
1009   void Interpreter::InterpretCommand( const std::vector<std::string>& words,
1010                                       CommandInfoType& info )
1011   {
1012     bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretCommand(...)"<<std::endl);
1013     
1014     // searches the command keyword
1015     CommandDictType::iterator c;
1016     c = mCommandDict.find(words[0]);
1017     if ( c == mCommandDict.end() ) {
1018       bbtkError(words[0]<<" : unknown command");
1019     }
1020
1021     // tests the number of args 
1022     if ( ( words.size()-1 < c->second.argmin ) ||
1023          ( words.size()-1 > c->second.argmax ) )
1024     {
1025        HelpCommand(words[0]);
1026        bbtkError(words[0]<<" : wrong number of arguments");
1027     }
1028
1029     info = c->second;
1030     bbtkDecTab("Interpreter",9);
1031   }
1032   //=======================================================================
1033
1034
1035   //=======================================================================
1036   /// Displays help on all the commands
1037 void Interpreter::Help(const std::vector<std::string>& words)
1038 {
1039     unsigned int nbarg = words.size()-1;
1040     
1041     if (nbarg==0) 
1042     {
1043        HelpCommands();
1044     }
1045     else if (nbarg==1) 
1046     {
1047       if (words[1]=="packages") 
1048       {
1049          PrintPackages(true);
1050          return;
1051       }
1052       try 
1053       {
1054           HelpCommand(words[1]);
1055       }
1056       catch (bbtk::Exception e) 
1057       {
1058          try 
1059          {
1060             HelpPackage(words[1]);
1061          }
1062          catch (bbtk::Exception f) 
1063          {
1064             try 
1065             {
1066                HelpBlackBox(words[1]);
1067             }
1068            catch (bbtk::Exception g) 
1069            {
1070               try
1071               {
1072                  this->mExecuter->ShowRelations(words[1],"0","9999");
1073               }
1074               catch (bbtk::Exception h){
1075                 bbtkError("\""<<words[1].c_str()
1076                           <<"\" is not a known command, package, black box type or black box name");
1077               }
1078            }
1079          }
1080        }
1081     }
1082     else if (nbarg==2) 
1083     {
1084       if (words[2]=="all")
1085       {
1086          if ( words[1]=="packages" )
1087          {
1088             PrintPackages(true,true);
1089             return;
1090           }
1091          try 
1092          {
1093             HelpPackage(words[1],true);
1094          }
1095          catch (bbtk::Exception f) 
1096          {
1097          }
1098      }
1099      else 
1100      {
1101         HelpCommand(words[0]);
1102         bbtkError(words[0]<<" : syntax error");
1103      }
1104   }
1105   else 
1106   {
1107      bbtkError("Should not reach here !!!");
1108   }
1109 }
1110   //=======================================================================
1111
1112    //===================================================================    
1113   /// Displays the Configuration
1114   void Interpreter::Config( bool verbose ) const
1115   {
1116     bbtkDebugMessageInc("Core",9,"Factory::Config"<<std::endl);
1117     
1118     ConfigurationFile cf = ConfigurationFile::GetInstance();
1119     
1120     const std::string config_xml_full_path      = cf.Get_config_xml_full_path();    
1121     const std::string description               = cf.Get_description();
1122     const std::string url                       = cf.Get_url();
1123     const std::string data_path                 = cf.Get_data_path();
1124     const std::string default_doc_tmp           = cf.Get_default_doc_tmp();    
1125     const std::string file_separator            = cf.Get_file_separator();    
1126     const std::vector<std::string>bbs_paths     = cf.Get_bbs_paths();
1127     const std::vector<std::string>package_paths = cf.Get_package_paths();
1128     
1129     bbtkMessage("Help",1, "============="   << std::endl);           
1130     bbtkMessage("Help",1, "Configuration"   << std::endl);
1131     bbtkMessage("Help",1, "============="   << std::endl);
1132     bbtkMessage("Help",1, "bbtk_config.xml   : [" << config_xml_full_path  << "]" << std::endl); 
1133     bbtkMessage("Help",1, "Documentation Url : [" << url             << "]" << std::endl);
1134     bbtkMessage("Help",1, "Data Path         : [" << data_path       << "]" << std::endl);
1135     bbtkMessage("Help",1, "Default Doc_tmp   : [" << default_doc_tmp << "]" << std::endl);
1136     bbtkMessage("Help",1, "File Separator    : [" << file_separator  << "]" << std::endl);
1137
1138     std::vector<std::string>::const_iterator i;
1139            
1140     bbtkMessage("Help",1, "BBS Paths   " << std::endl);     
1141     for (i = bbs_paths.begin(); i!=bbs_paths.end(); ++i )
1142     {
1143       bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1144     }    
1145     
1146     bbtkMessage("Help",1, "PACKAGE Paths : " << std::endl);     
1147     for (i = package_paths.begin(); i!=package_paths.end(); ++i )
1148     {
1149       bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1150     }
1151
1152     bbtkDebugDecTab("Core",9);
1153   }  
1154
1155   //=======================================================================
1156   /// Displays help on all the commands
1157   void Interpreter::HelpCommands()
1158   {
1159     std::cout << "Available commands :" << std::endl;
1160     CommandDictType::iterator i;
1161     for ( i =  mCommandDict.begin();
1162           i != mCommandDict.end();
1163         ++i) {
1164               std::cout << " " << i->first << std::endl;
1165       //      std::cout << "   usage : " << i->second.syntax << std::endl;
1166       //     std::cout << "    " << i->second.help << std::endl;
1167  
1168     }
1169   }
1170   //=======================================================================
1171
1172
1173   //=======================================================================
1174   /// Displays help on a particular commands
1175   void Interpreter::HelpCommand(const std::string& s)
1176   {
1177     CommandDictType::iterator c;
1178     c = mCommandDict.find(s);
1179     if ( c == mCommandDict.end() ) {
1180       bbtkError(s<<" : Unknown command");
1181     }
1182     //    std::cout << " " << s << " : "<<  std::endl;
1183     //    CommandParamDictType::iterator i;
1184     //    for ( i =  c->second.begin();
1185     //      i != c->second.end();
1186     //      ++i) {
1187     std::cout << " usage : " << c->second.syntax << std::endl;
1188     std::cout << "  " << c->second.help << std::endl;
1189     
1190   }
1191   //=======================================================================
1192
1193
1194   //=======================================================================
1195   /// Fills the vector commands with the commands which 
1196   /// have the first n chars of buf for prefix
1197   /// TODO : skip initial spaces in buf and also return the position of first
1198   /// non blank char in buf
1199   void Interpreter::FindCommandsWithPrefix( char* buf,
1200                                             int n,
1201                                             std::vector<std::string>& commands )
1202   {
1203     CommandDictType::const_iterator i;
1204     for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1205     {
1206       if ((i->first).find(buf,0,n) == 0) 
1207         commands.push_back(i->first);
1208     }
1209   }
1210   //=======================================================================
1211
1212
1213   
1214   //=======================================================================
1215 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1216   
1217   inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1218   inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1219   
1220   // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1221   // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1222   // E.G. STORE THIS IN bbtk_config.xml
1223 #define BBTK_UP_ARROW_KBCODE    0x00415B1B
1224 #define BBTK_DOWN_ARROW_KBCODE  0x00425B1B
1225 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1226 #define BBTK_LEFT_ARROW_KBCODE  0x00445B1B
1227 #define BBTK_BACKSPACE_KBCODE   0x00000008
1228 #define BBTK_DEL_KBCODE         0x0000007F
1229 #define BBTK_SPACE_KBCODE       0x00000020 
1230
1231   //=======================================================================
1232   void Interpreter::GetLineFromPrompt(std::string& s)
1233   {
1234     int c;
1235     int ind=0;
1236     
1237     int MAX_LINE_SIZE = 160;
1238     int MAX_HISTORY_SIZE = 100;
1239     
1240     char* newline = new char[MAX_LINE_SIZE];
1241     memset(newline,0,MAX_LINE_SIZE);
1242     char* histline = new char[MAX_LINE_SIZE];
1243     memset(histline,0,MAX_LINE_SIZE);
1244     
1245     char* line = newline;
1246     int hist = mHistory.size();
1247     
1248     
1249     write(1,"> ",2);
1250     while(1)
1251     {
1252        c=0;
1253        read ( STDIN_FILENO, &c, 4) ;
1254
1255        bbtkDebugMessage("Debug",9,"[0x"<<std::hex<<c<<"]\n");
1256
1257        // Printable character
1258        if ( (ind<MAX_LINE_SIZE-1) &&
1259             ( c >= BBTK_SPACE_KBCODE ) && 
1260             ( c <  BBTK_DEL_KBCODE )) 
1261        {
1262           PrintChar(c);
1263           line[ind++]=c;
1264        }
1265       // CR
1266        else if (c=='\n')
1267        {
1268        // delete the unused line
1269           if (line==newline)
1270               delete histline;
1271           else
1272               delete newline;
1273    
1274     // empty lines are not stored in from history
1275           if (strlen(line)) 
1276           {
1277              // if history too long : delete oldest command
1278              if (mHistory.size()>MAX_HISTORY_SIZE) 
1279              {
1280                 delete mHistory.front();
1281                 mHistory.pop_front();
1282              }
1283              mHistory.push_back(line);
1284           }
1285           break;
1286         }
1287        // Backspace
1288         else if ( (ind>0) && 
1289                   ((c == BBTK_BACKSPACE_KBCODE) ||
1290                    (c == BBTK_DEL_KBCODE)) )
1291           {
1292             line[ind--]=' ';
1293             BackSpace();
1294           }
1295         // Tab 
1296         else if (c=='\t')
1297           {
1298             // TODO : Command completion  
1299             std::vector<std::string> commands;
1300             FindCommandsWithPrefix( line,ind,commands);
1301             if (commands.size()==1) 
1302               {
1303                 std::string com = *commands.begin();
1304                 for (; ind<com.size(); ++ind) 
1305                   {
1306                     PrintChar(com[ind]); 
1307                     line[ind]=com[ind];
1308                   }
1309                 PrintChar(' '); 
1310                 line[ind++]=' ';
1311               }
1312             else if (commands.size()>1) 
1313               {
1314                 std::vector<std::string>::iterator i;
1315                 write(1,"\n",1);
1316                 for (i=commands.begin();i!=commands.end();++i) 
1317                   {
1318                     write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1319                     PrintChar(' ');
1320                   }
1321                 write(STDOUT_FILENO,"\n> ",3);
1322                 //for (int j=0;j<ind;++j) 
1323                   //{
1324                     write(STDOUT_FILENO,line,ind); 
1325                     //  }
1326               }
1327           }
1328         // Arrow up : back in history
1329         else if (c==BBTK_UP_ARROW_KBCODE)
1330           {
1331             if (hist) 
1332               {
1333                 // erase current line
1334                 while (ind--) BackSpace();
1335                 // 
1336                 hist--;
1337                 // 
1338                 strcpy(histline,mHistory[hist]);
1339                 line = histline;
1340                 ind = strlen(line);
1341                 
1342                 write(STDOUT_FILENO,line,ind);
1343               }
1344           }
1345         // Arrow down : down in history
1346         else if (c==BBTK_DOWN_ARROW_KBCODE)
1347           {
1348             if (hist<mHistory.size()-1) 
1349               {
1350                 // erase current line
1351                 while (ind--) BackSpace();
1352                 // 
1353                 hist++;
1354                 // 
1355                 strcpy(histline,mHistory[hist]);
1356                 line = histline;
1357                 ind = strlen(line);
1358                 
1359                 write(STDOUT_FILENO,line,ind);
1360               }
1361             // end of history : switch back to newline
1362             else if (hist==mHistory.size()-1)
1363               {
1364                 // erase current line
1365                 while (ind--) BackSpace();
1366                 // 
1367                 hist++;
1368                 // 
1369                 line = newline;
1370                 ind = strlen(line);
1371                 
1372                 write(STDOUT_FILENO,line,ind);
1373               }
1374           }
1375         // Arrow right
1376         else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1377           {
1378             PrintChar(line[ind]);
1379             ind++;
1380           }
1381
1382         // Arrow left
1383         else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1384           {
1385             PrintChar('\b');
1386             ind--;
1387     
1388           }
1389
1390       }
1391     write(STDOUT_FILENO,"\n\r",2);
1392     
1393     
1394     s = line;
1395     
1396   }
1397 #else
1398
1399   //=======================================================================
1400   void Interpreter::GetLineFromPrompt(std::string& s)
1401   {  
1402     s.clear();
1403
1404     putchar('>');
1405     putchar(' ');
1406
1407     do 
1408     {
1409       char c = getchar();
1410       if (c=='\n') 
1411       {
1412         putchar('\n');
1413         break;
1414       }
1415       if (c=='\t') 
1416       {
1417         // putchar('T');
1418         continue;
1419       }
1420       // putchar(c);
1421       s += c;
1422     } 
1423     while (true);  
1424     
1425   }
1426   //=======================================================================  
1427
1428 #endif
1429
1430
1431
1432   //=======================================================================
1433   void Interpreter::CommandLineInterpreter()
1434   {
1435     bbtkDebugMessageInc("Interpreter",9,
1436                         "Interpreter::CommandLineInterpreter()"<<std::endl);
1437     
1438 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT  
1439     // Initialise the tty in non canonical mode with no echo
1440     // oter remembers the previous settings to restore them after 
1441     struct termios ter,oter;
1442     tcgetattr(0,&ter);
1443     oter=ter;
1444     ter.c_lflag &= ~ECHO;
1445     ter.c_lflag &= ~ICANON;
1446     ter.c_cc[VMIN]=1;
1447     ter.c_cc[VTIME]=0;
1448     tcsetattr(0,TCSANOW,&ter);
1449 #endif
1450     
1451     mCommandLine = true;
1452     bool again = true;
1453     bool insideComment = false; // for multiline comment  
1454     do 
1455     {
1456       try
1457       {
1458         std::string line;
1459         GetLineFromPrompt(line);
1460         InterpretLine(line, insideComment);
1461       }
1462       catch (QuitException e)
1463       {
1464         again = false;
1465       }
1466       catch (bbtk::Exception e) 
1467       {
1468         e.Print();
1469       }
1470         catch (std::exception& e) 
1471       {
1472         std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
1473       }
1474       catch (...)
1475       {
1476         std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
1477       }
1478     }
1479     while (again);
1480   
1481 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1482     tcsetattr(0,TCSANOW,&oter);
1483 #endif
1484   
1485     std::cout << "Good bye !" << std::endl;
1486     
1487     bbtkDebugDecTab("Interpreter",9);
1488   }
1489
1490   //=======================================================================
1491   void Interpreter::Graph(const std::vector<std::string>& words)
1492   {
1493     std::string page;
1494     bool system_display = true;
1495
1496 #ifdef _USE_WXWIDGETS_
1497     if ( WxConsole::GetInstance() != 0 ) system_display = false; 
1498 #endif
1499  
1500     if (words.size()==1) 
1501     {
1502       page = mExecuter->ShowGraph(".","0","0","","","",system_display);
1503     }
1504     else if (words.size()==2) 
1505     {
1506       page = mExecuter->ShowGraph(words[1],"0","0","","","",system_display);
1507     }
1508     else if (words.size()==3) 
1509     {
1510       page = mExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
1511     }
1512     else if (words.size()==4) 
1513     {
1514       page = mExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
1515     } 
1516     else if (words.size()==5) 
1517     {
1518       page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
1519     } 
1520     else if (words.size()==6) 
1521     {
1522       page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
1523     } 
1524     else if (words.size()==7) 
1525     {
1526       page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
1527     } 
1528
1529 #ifdef _USE_WXWIDGETS_
1530     if ( WxConsole::GetInstance() != 0 )
1531       WxConsole::GetInstance()->ShowHtmlPage(page);
1532 #endif
1533   }
1534   //=======================================================================
1535
1536
1537 }//namespace
1538
1539