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