]> Creatis software - bbtk.git/blob - kernel/src/bbtkInterpreter.cxx
Absolute expression for path name + '*' didn't work
[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 15:29:07 $
7   Version:   $Revision: 1.16 $
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   // use ./directory/subdir/scrname.bbs
747   //
748   
749     bbtkDebugMessageInc("Interpreter",9,"Interpreter::SwitchToFile( \""
750                          <<name<<"\")"<<std::endl);
751
752 // to be remove in final version
753 // use : Config v
754 //verbose = true;
755     std::vector<std::string> script_paths;
756     std::string fullPathScriptName;  // full path script name
757     std::string pkgname;             // e.g. <scriptname>.bbs
758     std::vector<std::string> Filenames;
759         
760     if (use_configuration_file)
761     {
762         // The following is *NOT* a debug time message :
763         // It's a user intended message.
764         // Please don't remove it.
765       if (verbose)
766          std::cout << "look for : [" << name << "] (use_configuration_file == TRUE)"  << std::endl;
767       script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
768     }
769     std::string upath;
770     pkgname = Utilities::ExtractScriptName(name,upath);
771 //std::cout <<"name [" <<   name << "] pkgname [" << pkgname << "] upath [" << upath << "]" << std::endl;    
772     bool fullnameGiven = false; 
773     bool foundFile     = false;
774
775     if(pkgname == "*") // =========================================== load all boxes (e.g. std/boxes/*)
776     {
777       int nbBssFiles;
778
779       if (upath[0]=='/' || upath[1] == ':' ) // ==== absolute name, load all .bbs files
780       {
781         int nbFiles = Utilities::Explore(upath, false, Filenames);
782         nbBssFiles = 0;
783         for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
784         {
785            if ((*i).substr((*i).size()-4, 4) != ".bbs")
786               continue;      // ignore non .bbs files
787            LoadScript(*i);
788            nbBssFiles++;
789         }
790         if (nbBssFiles==0)
791            if (verbose)
792               std::cout << "WARNING : No '.bbs' file found in [" << upath << "]" << std::endl;
793
794         return;
795       }
796       
797
798       std::string path;
799       std::vector<std::string>::iterator i;
800       std::string fullDirectoryName;
801       for (i=script_paths.begin();i!=script_paths.end();++i)// ==== relative name, iterate + load all .bbs files
802       {
803         path = *i;
804
805        // we *really* want '.' to be the current working directory
806         if (path == ".") {
807           char buf[2048]; // for getcwd
808           char * currentDir = getcwd(buf, 2048);
809           std::string cwd(currentDir);
810           path = currentDir;
811         }
812
813         fullDirectoryName = Utilities::MakePkgnameFromPath(path, upath, false);
814 //std::cout <<"fullpath [" <<   fullDirectoryName << "]" <<std::endl;
815       // Check if library exists           
816         if ( ! Utilities::IsDirectory(fullDirectoryName) )
817         {
818         // The following is *NOT* a debug time message :
819         // It's a user intended message.
820         // Please don't remove it.
821           if (verbose)
822             std::cout <<"   [" <<fullDirectoryName <<"] : doesn't exist" <<std::endl;
823           continue;  // try next path
824         }
825         foundFile = true;
826
827
828         int nbFiles = Utilities::Explore(fullDirectoryName, false, Filenames);
829 // std::cout << "=================nbFiles " << nbFiles << std::endl;
830         nbBssFiles = 0;
831         for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
832         {
833            if ((*i).substr((*i).size()-4, 4) != ".bbs")
834               continue;      // ignore non .bbs files
835            LoadScript(*i);
836            nbBssFiles++;
837         }
838         if (nbBssFiles==0)
839            if (verbose)
840               std::cout << "WARNING : No '.bbs' file found in [" << fullDirectoryName << "]" << std::endl;
841            
842         break; // a directory was found; we stop iterating
843        }
844        return;
845     }
846
847     //std::string::size_type slash_position = name.find_last_of("/\\");
848
849     // if name starts with a / or a . or contains : user is assumed to have passed a relative/absolute name
850     // (not only a plain script name)
851     // we trust him, and try to expland the directory name
852     // WARNING : starting from current local directory :  ./whatYouWant  (./ mandatory!)
853
854     if (name[0]=='/' || name[1] == ':' || name[0]=='.')  // absolute path (linux/windows) or relative path
855     { 
856
857       // ===========================================================check user supplied location
858       fullnameGiven = true;
859
860       fullPathScriptName =  Utilities::ExpandLibName(name, verbose);
861
862       // allow user to always forget ".bbs"
863       int l = fullPathScriptName.size();
864
865       if (l!=0) {
866       
867       if (l>4)
868       {
869          if (fullPathScriptName.substr(l-4, 4) != ".bbs")
870          {
871             fullPathScriptName = fullPathScriptName + ".bbs";
872          }
873       }
874       else
875       {
876          fullPathScriptName = fullPathScriptName + ".bbs";   
877       }
878
879         if ( Utilities::FileExists(fullPathScriptName))
880         {
881           foundFile = true;
882         }
883       } // endif l != 0
884     }
885     else 
886
887       // =============================================================== iterate on the paths
888       {
889       std::string path;
890       std::vector<std::string>::iterator i;
891       for (i=script_paths.begin();i!=script_paths.end();++i)
892       {
893
894         path = *i;
895        // we *really* want '.' to be the current working directory
896         if (path == ".") {
897           char buf[2048]; // for getcwd
898           char * currentDir = getcwd(buf, 2048);
899           std::string cwd(currentDir);
900           path = currentDir;
901         }
902
903        // fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true); //pkgname);
904
905             fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true);
906 //std::cout << "FULL PATH = "<<fullPathScriptName<<std::endl;
907
908       // Check if library exists
909         if ( ! Utilities::FileExists(fullPathScriptName) )
910         {
911         // The following is *NOT* a debug time message :
912         // It's a user intended message.
913         // Please don't remove it.
914           if (verbose)
915             std::cout <<"   [" <<fullPathScriptName <<"] : doesn't exist" <<std::endl;
916           continue;  // try next path
917         }
918         if (verbose)
919            std::cout <<"   [" <<fullPathScriptName <<"] : found" <<std::endl;        
920         foundFile = true;
921         break; // a script was found; we stop iterating
922
923       } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
924     }
925
926     if (!foundFile)
927     {
928        if (fullnameGiven)
929          if(fullPathScriptName == "")
930             bbtkError("Path ["<<upath<<"] doesn't exist");
931          else
932             bbtkError("Script ["<<fullPathScriptName<<"] not found");
933        else
934           bbtkError("No ["<<pkgname<<".bbs] script found");
935        return;    
936     }
937     else
938        LoadScript(fullPathScriptName);
939
940     return;
941   }   
942    
943
944   //=======================================================================
945
946   void Interpreter::LoadScript( std::string fullPathScriptName)
947   {
948     bbtkMessage("Interpreter",1,fullPathScriptName<<" found"<<std::endl);
949
950     std::ifstream* s;      
951     s = new std::ifstream;
952     s->open(fullPathScriptName.c_str());
953     if (!s->good()) 
954     {
955         bbtkError("Could not open file ["<<fullPathScriptName<<"]");
956         return;     
957     }
958     
959     if (verbose)
960        std::cout << "   -->[" << fullPathScriptName << "] found" << std::endl;
961
962     mFile.push_back(s);
963     mFileName.push_back(fullPathScriptName);
964     mLine.push_back(0);
965     return;  
966   }
967
968   //=======================================================================
969   /**
970    *  
971    */
972   void Interpreter::CloseCurrentFile()
973   {
974     bbtkDebugMessage("Interpreter",9,"Interpreter::CloseCurrentFile()"
975                       <<std::endl);
976     
977     if (mFile.size()==0) 
978     {
979       bbtkDebugMessage("Interpreter",9," -> no file left open"<<std::endl);
980       return;
981     }
982
983     mFile.back()->close();
984     delete mFile.back();
985     mFile.pop_back();
986     bbtkDebugMessage("Interpreter",9,
987                      " Closing file '"<<mFileName.back()<<"'"<<std::endl);
988     
989     mFileName.pop_back();
990     mLine.pop_back();
991     bbtkDebugMessage("Interpreter",9," Remains "
992                      <<mFile.size()
993                      <<" open"<<std::endl);
994     bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseCurrentFile()"
995                      <<std::endl);
996   }
997   //=======================================================================
998
999  //=======================================================================
1000   /**
1001    *  
1002    */
1003   void Interpreter::CloseAllFiles()
1004   {
1005     bbtkDebugMessage("Interpreter",9,"Interpreter::CloseAllFiles()"
1006                       <<std::endl);
1007     
1008     while (mFile.size() != 0) 
1009     {
1010       mFile.back()->close();
1011       delete mFile.back();
1012       mFile.pop_back();
1013       bbtkDebugMessage("Interpreter",9,
1014                       " Closing file '"<<mFileName.back()<<"'"<<std::endl);
1015       mFileName.pop_back();
1016       mLine.pop_back();
1017     }
1018     bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseAllFiles()"
1019                       <<std::endl);
1020   }
1021   //=======================================================================
1022
1023
1024
1025   //=======================================================================
1026   /**
1027    *  
1028    */
1029   void Interpreter::InterpretCommand( const std::vector<std::string>& words,
1030                                       CommandInfoType& info )
1031   {
1032     bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretCommand(...)"<<std::endl);
1033     
1034     // searches the command keyword
1035     CommandDictType::iterator c;
1036     c = mCommandDict.find(words[0]);
1037     if ( c == mCommandDict.end() ) {
1038       bbtkError(words[0]<<" : unknown command");
1039     }
1040
1041     // tests the number of args 
1042     if ( ( words.size()-1 < c->second.argmin ) ||
1043          ( words.size()-1 > c->second.argmax ) )
1044     {
1045        HelpCommand(words[0]);
1046        bbtkError(words[0]<<" : wrong number of arguments");
1047     }
1048
1049     info = c->second;
1050     bbtkDecTab("Interpreter",9);
1051   }
1052   //=======================================================================
1053
1054
1055   //=======================================================================
1056   /// Displays help on all the commands
1057 void Interpreter::Help(const std::vector<std::string>& words)
1058 {
1059     unsigned int nbarg = words.size()-1;
1060     
1061     if (nbarg==0) 
1062     {
1063        HelpCommands();
1064     }
1065     else if (nbarg==1) 
1066     {
1067       if (words[1]=="packages") 
1068       {
1069          PrintPackages(true);
1070          return;
1071       }
1072       try 
1073       {
1074           HelpCommand(words[1]);
1075       }
1076       catch (bbtk::Exception e) 
1077       {
1078          try 
1079          {
1080             HelpPackage(words[1]);
1081          }
1082          catch (bbtk::Exception f) 
1083          {
1084             try 
1085             {
1086                HelpBlackBox(words[1]);
1087             }
1088            catch (bbtk::Exception g) 
1089            {
1090               try
1091               {
1092                  this->mExecuter->ShowRelations(words[1],"0","9999");
1093               }
1094               catch (bbtk::Exception h){
1095                 bbtkError("\""<<words[1].c_str()
1096                           <<"\" is not a known command, package, black box type or black box name");
1097               }
1098            }
1099          }
1100        }
1101     }
1102     else if (nbarg==2) 
1103     {
1104       if (words[2]=="all")
1105       {
1106          if ( words[1]=="packages" )
1107          {
1108             PrintPackages(true,true);
1109             return;
1110           }
1111          try 
1112          {
1113             HelpPackage(words[1],true);
1114          }
1115          catch (bbtk::Exception f) 
1116          {
1117          }
1118      }
1119      else 
1120      {
1121         HelpCommand(words[0]);
1122         bbtkError(words[0]<<" : syntax error");
1123      }
1124   }
1125   else 
1126   {
1127      bbtkError("Should not reach here !!!");
1128   }
1129 }
1130   //=======================================================================
1131
1132    //===================================================================    
1133   /// Displays the Configuration
1134   void Interpreter::Config( bool verbose ) const
1135   {
1136     bbtkDebugMessageInc("Core",9,"Factory::Config"<<std::endl);
1137     
1138     ConfigurationFile cf = ConfigurationFile::GetInstance();
1139     
1140     const std::string config_xml_full_path      = cf.Get_config_xml_full_path();    
1141     const std::string description               = cf.Get_description();
1142     const std::string url                       = cf.Get_url();
1143     const std::string data_path                 = cf.Get_data_path();
1144     const std::string default_doc_tmp           = cf.Get_default_doc_tmp();    
1145     const std::string file_separator            = cf.Get_file_separator();    
1146     const std::vector<std::string>bbs_paths     = cf.Get_bbs_paths();
1147     const std::vector<std::string>package_paths = cf.Get_package_paths();
1148     
1149     bbtkMessage("Help",1, "============="   << std::endl);           
1150     bbtkMessage("Help",1, "Configuration"   << std::endl);
1151     bbtkMessage("Help",1, "============="   << std::endl);
1152     bbtkMessage("Help",1, "bbtk_config.xml   : [" << config_xml_full_path  << "]" << std::endl); 
1153     bbtkMessage("Help",1, "Documentation Url : [" << url             << "]" << std::endl);
1154     bbtkMessage("Help",1, "Data Path         : [" << data_path       << "]" << std::endl);
1155     bbtkMessage("Help",1, "Default Doc_tmp   : [" << default_doc_tmp << "]" << std::endl);
1156     bbtkMessage("Help",1, "File Separator    : [" << file_separator  << "]" << std::endl);
1157
1158     std::vector<std::string>::const_iterator i;
1159            
1160     bbtkMessage("Help",1, "BBS Paths   " << std::endl);     
1161     for (i = bbs_paths.begin(); i!=bbs_paths.end(); ++i )
1162     {
1163       bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1164     }    
1165     
1166     bbtkMessage("Help",1, "PACKAGE Paths : " << std::endl);     
1167     for (i = package_paths.begin(); i!=package_paths.end(); ++i )
1168     {
1169       bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1170     }
1171
1172     bbtkDebugDecTab("Core",9);
1173   }  
1174
1175   //=======================================================================
1176   /// Displays help on all the commands
1177   void Interpreter::HelpCommands()
1178   {
1179     std::cout << "Available commands :" << std::endl;
1180     CommandDictType::iterator i;
1181     for ( i =  mCommandDict.begin();
1182           i != mCommandDict.end();
1183         ++i) {
1184               std::cout << " " << i->first << std::endl;
1185       //      std::cout << "   usage : " << i->second.syntax << std::endl;
1186       //     std::cout << "    " << i->second.help << std::endl;
1187  
1188     }
1189   }
1190   //=======================================================================
1191
1192
1193   //=======================================================================
1194   /// Displays help on a particular commands
1195   void Interpreter::HelpCommand(const std::string& s)
1196   {
1197     CommandDictType::iterator c;
1198     c = mCommandDict.find(s);
1199     if ( c == mCommandDict.end() ) {
1200       bbtkError(s<<" : Unknown command");
1201     }
1202     //    std::cout << " " << s << " : "<<  std::endl;
1203     //    CommandParamDictType::iterator i;
1204     //    for ( i =  c->second.begin();
1205     //      i != c->second.end();
1206     //      ++i) {
1207     std::cout << " usage : " << c->second.syntax << std::endl;
1208     std::cout << "  " << c->second.help << std::endl;
1209     
1210   }
1211   //=======================================================================
1212
1213
1214   //=======================================================================
1215   /// Fills the vector commands with the commands which 
1216   /// have the first n chars of buf for prefix
1217   /// TODO : skip initial spaces in buf and also return the position of first
1218   /// non blank char in buf
1219   void Interpreter::FindCommandsWithPrefix( char* buf,
1220                                             int n,
1221                                             std::vector<std::string>& commands )
1222   {
1223     CommandDictType::const_iterator i;
1224     for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1225     {
1226       if ((i->first).find(buf,0,n) == 0) 
1227         commands.push_back(i->first);
1228     }
1229   }
1230   //=======================================================================
1231
1232
1233   
1234   //=======================================================================
1235 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1236   
1237   inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1238   inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1239   
1240   // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1241   // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1242   // E.G. STORE THIS IN bbtk_config.xml
1243 #define BBTK_UP_ARROW_KBCODE    0x00415B1B
1244 #define BBTK_DOWN_ARROW_KBCODE  0x00425B1B
1245 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1246 #define BBTK_LEFT_ARROW_KBCODE  0x00445B1B
1247 #define BBTK_BACKSPACE_KBCODE   0x00000008
1248 #define BBTK_DEL_KBCODE         0x0000007F
1249 #define BBTK_SPACE_KBCODE       0x00000020 
1250
1251   //=======================================================================
1252   void Interpreter::GetLineFromPrompt(std::string& s)
1253   {
1254     int c;
1255     int ind=0;
1256     
1257     int MAX_LINE_SIZE = 160;
1258     int MAX_HISTORY_SIZE = 100;
1259     
1260     char* newline = new char[MAX_LINE_SIZE];
1261     memset(newline,0,MAX_LINE_SIZE);
1262     char* histline = new char[MAX_LINE_SIZE];
1263     memset(histline,0,MAX_LINE_SIZE);
1264     
1265     char* line = newline;
1266     int hist = mHistory.size();
1267     
1268     
1269     write(1,"> ",2);
1270     while(1)
1271     {
1272        c=0;
1273        read ( STDIN_FILENO, &c, 4) ;
1274
1275        bbtkDebugMessage("Debug",9,"[0x"<<std::hex<<c<<"]\n");
1276
1277        // Printable character
1278        if ( (ind<MAX_LINE_SIZE-1) &&
1279             ( c >= BBTK_SPACE_KBCODE ) && 
1280             ( c <  BBTK_DEL_KBCODE )) 
1281        {
1282           PrintChar(c);
1283           line[ind++]=c;
1284        }
1285       // CR
1286        else if (c=='\n')
1287        {
1288        // delete the unused line
1289           if (line==newline)
1290               delete histline;
1291           else
1292               delete newline;
1293    
1294     // empty lines are not stored in from history
1295           if (strlen(line)) 
1296           {
1297              // if history too long : delete oldest command
1298              if (mHistory.size()>MAX_HISTORY_SIZE) 
1299              {
1300                 delete mHistory.front();
1301                 mHistory.pop_front();
1302              }
1303              mHistory.push_back(line);
1304           }
1305           break;
1306         }
1307        // Backspace
1308         else if ( (ind>0) && 
1309                   ((c == BBTK_BACKSPACE_KBCODE) ||
1310                    (c == BBTK_DEL_KBCODE)) )
1311           {
1312             line[ind--]=' ';
1313             BackSpace();
1314           }
1315         // Tab 
1316         else if (c=='\t')
1317           {
1318             // TODO : Command completion  
1319             std::vector<std::string> commands;
1320             FindCommandsWithPrefix( line,ind,commands);
1321             if (commands.size()==1) 
1322               {
1323                 std::string com = *commands.begin();
1324                 for (; ind<com.size(); ++ind) 
1325                   {
1326                     PrintChar(com[ind]); 
1327                     line[ind]=com[ind];
1328                   }
1329                 PrintChar(' '); 
1330                 line[ind++]=' ';
1331               }
1332             else if (commands.size()>1) 
1333               {
1334                 std::vector<std::string>::iterator i;
1335                 write(1,"\n",1);
1336                 for (i=commands.begin();i!=commands.end();++i) 
1337                   {
1338                     write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1339                     PrintChar(' ');
1340                   }
1341                 write(STDOUT_FILENO,"\n> ",3);
1342                 //for (int j=0;j<ind;++j) 
1343                   //{
1344                     write(STDOUT_FILENO,line,ind); 
1345                     //  }
1346               }
1347           }
1348         // Arrow up : back in history
1349         else if (c==BBTK_UP_ARROW_KBCODE)
1350           {
1351             if (hist) 
1352               {
1353                 // erase current line
1354                 while (ind--) BackSpace();
1355                 // 
1356                 hist--;
1357                 // 
1358                 strcpy(histline,mHistory[hist]);
1359                 line = histline;
1360                 ind = strlen(line);
1361                 
1362                 write(STDOUT_FILENO,line,ind);
1363               }
1364           }
1365         // Arrow down : down in history
1366         else if (c==BBTK_DOWN_ARROW_KBCODE)
1367           {
1368             if (hist<mHistory.size()-1) 
1369               {
1370                 // erase current line
1371                 while (ind--) BackSpace();
1372                 // 
1373                 hist++;
1374                 // 
1375                 strcpy(histline,mHistory[hist]);
1376                 line = histline;
1377                 ind = strlen(line);
1378                 
1379                 write(STDOUT_FILENO,line,ind);
1380               }
1381             // end of history : switch back to newline
1382             else if (hist==mHistory.size()-1)
1383               {
1384                 // erase current line
1385                 while (ind--) BackSpace();
1386                 // 
1387                 hist++;
1388                 // 
1389                 line = newline;
1390                 ind = strlen(line);
1391                 
1392                 write(STDOUT_FILENO,line,ind);
1393               }
1394           }
1395         // Arrow right
1396         else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1397           {
1398             PrintChar(line[ind]);
1399             ind++;
1400           }
1401
1402         // Arrow left
1403         else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1404           {
1405             PrintChar('\b');
1406             ind--;
1407     
1408           }
1409
1410       }
1411     write(STDOUT_FILENO,"\n\r",2);
1412     
1413     
1414     s = line;
1415     
1416   }
1417 #else
1418
1419   //=======================================================================
1420   void Interpreter::GetLineFromPrompt(std::string& s)
1421   {  
1422     s.clear();
1423
1424     putchar('>');
1425     putchar(' ');
1426
1427     do 
1428     {
1429       char c = getchar();
1430       if (c=='\n') 
1431       {
1432         putchar('\n');
1433         break;
1434       }
1435       if (c=='\t') 
1436       {
1437         // putchar('T');
1438         continue;
1439       }
1440       // putchar(c);
1441       s += c;
1442     } 
1443     while (true);  
1444     
1445   }
1446   //=======================================================================  
1447
1448 #endif
1449
1450
1451
1452   //=======================================================================
1453   void Interpreter::CommandLineInterpreter()
1454   {
1455     bbtkDebugMessageInc("Interpreter",9,
1456                         "Interpreter::CommandLineInterpreter()"<<std::endl);
1457     
1458 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT  
1459     // Initialise the tty in non canonical mode with no echo
1460     // oter remembers the previous settings to restore them after 
1461     struct termios ter,oter;
1462     tcgetattr(0,&ter);
1463     oter=ter;
1464     ter.c_lflag &= ~ECHO;
1465     ter.c_lflag &= ~ICANON;
1466     ter.c_cc[VMIN]=1;
1467     ter.c_cc[VTIME]=0;
1468     tcsetattr(0,TCSANOW,&ter);
1469 #endif
1470     
1471     mCommandLine = true;
1472     bool again = true;
1473     bool insideComment = false; // for multiline comment  
1474     do 
1475     {
1476       try
1477       {
1478         std::string line;
1479         GetLineFromPrompt(line);
1480         InterpretLine(line, insideComment);
1481       }
1482       catch (QuitException e)
1483       {
1484         again = false;
1485       }
1486       catch (bbtk::Exception e) 
1487       {
1488         e.Print();
1489       }
1490         catch (std::exception& e) 
1491       {
1492         std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
1493       }
1494       catch (...)
1495       {
1496         std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
1497       }
1498     }
1499     while (again);
1500   
1501 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1502     tcsetattr(0,TCSANOW,&oter);
1503 #endif
1504   
1505     std::cout << "Good bye !" << std::endl;
1506     
1507     bbtkDebugDecTab("Interpreter",9);
1508   }
1509
1510   //=======================================================================
1511   void Interpreter::Graph(const std::vector<std::string>& words)
1512   {
1513     std::string page;
1514     bool system_display = true;
1515
1516 #ifdef _USE_WXWIDGETS_
1517     if ( WxConsole::GetInstance() != 0 ) system_display = false; 
1518 #endif
1519  
1520     if (words.size()==1) 
1521     {
1522       page = mExecuter->ShowGraph(".","0","0","","","",system_display);
1523     }
1524     else if (words.size()==2) 
1525     {
1526       page = mExecuter->ShowGraph(words[1],"0","0","","","",system_display);
1527     }
1528     else if (words.size()==3) 
1529     {
1530       page = mExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
1531     }
1532     else if (words.size()==4) 
1533     {
1534       page = mExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
1535     } 
1536     else if (words.size()==5) 
1537     {
1538       page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
1539     } 
1540     else if (words.size()==6) 
1541     {
1542       page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
1543     } 
1544     else if (words.size()==7) 
1545     {
1546       page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
1547     } 
1548
1549 #ifdef _USE_WXWIDGETS_
1550     if ( WxConsole::GetInstance() != 0 )
1551       WxConsole::GetInstance()->ShowHtmlPage(page);
1552 #endif
1553   }
1554   //=======================================================================
1555
1556
1557 }//namespace
1558
1559