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