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