]> 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/05 08:25:22 $
7   Version:   $Revision: 1.20 $
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)
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 = 0;
161     info.code = cConfig;
162     info.syntax = "config";
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     bbtkDebugDecTab("Interpreter",9);
291   }
292   //=======================================================================
293
294
295   //=======================================================================
296   /**
297    *  
298    */
299   void Interpreter::InterpretFile( const std::string& filename,  
300                                    bool use_configuration_file)
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);
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         Config();            
552         break;
553         
554       case cReset :  // EED
555         this->mExecuter->Reset();
556         break;
557         
558       case cInclude :
559         if (mCommandLine) 
560         {
561            InterpretFile(words[1], true ); // true : better pass use_config_file
562         }
563         else 
564         {
565             SwitchToFile(words[1], true ); // true : better pass use_config_file
566         }
567         break;
568         
569       case cLoad:
570         LoadPackage(words[1], true ); // true : better pass use_config_file
571         break;
572         
573       case cUnload:
574         UnLoadPackage(words[1]);
575         break;
576         
577       case cQuit :
578         throw QuitException();
579         break;
580         
581          case cWorkspace :
582         if (words.size() == 2) 
583         {
584            if (words[1]=="freeze")        mExecuter->SetNoExecMode(true);
585            else if (words[1]=="unfreeze") mExecuter->SetNoExecMode(false);
586         }
587         else 
588         {
589            mExecuter->SetWorkspaceName(words[2]);
590         }
591         break;
592         
593       default:
594         bbtkInternalError("should not reach here !!!");
595    }
596     
597    bbtkDecTab("Interpreter",9);
598 }
599   //=======================================================================  
600
601
602
603
604
605   //=======================================================================
606   /**
607    *  
608    */
609 void Interpreter::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
610 {
611     bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
612  
613     std::string delimiters = "\"";
614     std::vector<std::string> quote;
615     Utilities::SplitString(str,delimiters,quote);
616
617     delimiters = " \t";
618     std::vector<std::string>::iterator i;
619     for (i=quote.begin(); i!=quote.end(); ) 
620     {
621        Utilities::SplitString(*i,delimiters,tokens);
622        ++i;
623        if (i!=quote.end()) 
624        {
625         //    bbtkDebugMessage("Interpreter",0,"\""<<*i<<"\""<<std::endl);
626           tokens.push_back(*i);
627           ++i;
628        }
629     }
630
631     for (i=tokens.begin(); i!=tokens.end(); ++i) 
632     {
633        bbtkDebugMessage("Interpreter",9,"["<<*i<<"] ");
634     }
635     bbtkDebugMessageCont("Interpreter",9,std::endl);
636
637     bbtkDebugDecTab("Interpreter",9);    
638  }
639   //=======================================================================
640
641
642   //=======================================================================
643   // Replaces substrings "\\n" by a real carriage return "\n"
644   void SubsBackslashN ( std::string& s )
645   {
646     std::string ss("\\n");
647     std::string::size_type pos = 0;
648     pos = s.find(ss,0);
649     char* cr = "\n";
650     while ( pos != std::string::npos )
651    {
652       s.replace(pos,2,cr,1);
653       pos = s.find(ss, pos-1);
654    } 
655   }
656   //=======================================================================
657
658
659   //=======================================================================
660   /**
661    *  
662    */
663   void Interpreter::Print( const std::string& str)
664   {
665     if (mExecuter->GetNoExecMode()) return;
666
667     bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
668
669     std::vector<std::string> chains;
670     std::string delimiters("$");
671
672     // Skip delimiters at beginning.
673     std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
674     bool is_text = true;
675     if (lastPos>0) is_text = false;
676   
677     // Find first delimiter.
678     std::string::size_type pos     = str.find_first_of(delimiters, lastPos);
679     
680     while (std::string::npos != pos || std::string::npos != lastPos)
681     {
682        if (is_text) 
683        {
684           // Found a text token, add it to the vector.
685           chains.push_back(str.substr(lastPos, pos - lastPos));
686        }
687        else 
688        {
689        // is an output (between $$) : decode 
690          std::string tok,box,output;
691          tok = str.substr(lastPos, pos - lastPos);
692          Utilities::SplitAroundFirstDot(tok,box,output);
693          chains.push_back( mExecuter->Get(box,output) );
694        }
695         // Skip delimiters.  Note the "not_of"
696        lastPos = str.find_first_not_of(delimiters, pos);
697         // Find next delimiter
698        pos = str.find_first_of(delimiters, lastPos);
699     //
700        is_text = !is_text;
701      }
702      std::vector<std::string>::iterator i;
703      for (i= chains.begin(); i!=chains.end(); ++i) 
704      {
705        //  bbtkMessage("Echo",1,*i);
706        SubsBackslashN(*i);
707        std::cout << *i;
708      }
709      std::cout << std::endl;
710      bbtkDebugDecTab("Interpreter",9);    
711  }
712
713   //=======================================================================
714   /**
715    *  
716    */
717
718 // ===================================================================================
719
720   void Interpreter::SwitchToFile( const std::string& name,
721                                   bool use_configuration_file )
722   {
723   // Note : in the following :
724   // name : the user supplied name 
725   //      - abreviated name    e.g.       scr   scr.bbs
726   //      - relative full name e.g.       ./scr.bbs   ../../scr.bbs 
727   //      - absolute full name e.g.       /home/usrname/proj/dir/scr.bbs
728   //          same for Windows, with      c:, d: ...
729   //
730   // use ./directory/subdir/scrname.bbs
731   //
732   
733     bbtkDebugMessageInc("Interpreter",9,"Interpreter::SwitchToFile( \""
734                          <<name<<"\")"<<std::endl);
735
736     std::vector<std::string> script_paths;
737     std::string fullPathScriptName;  // full path script name
738     std::string pkgname;             // e.g. <scriptname>.bbs
739     std::vector<std::string> Filenames;
740         
741     if (use_configuration_file)
742     {
743         // The following is *NOT* a debug time message :
744         // It's a user intended message.
745         // Please don't remove it.
746       bbtkMessage("Interpreter",1,
747                   "look for : [" << name 
748                   << "] (use_configuration_file == TRUE)" << std::endl);
749       script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
750     }
751     std::string upath;
752     pkgname = Utilities::ExtractScriptName(name,upath);
753
754     bool fullnameGiven = false; 
755     bool foundFile     = false;
756
757     if(pkgname == "*") // =========================================== load all boxes (e.g. std/boxes/*)
758     {
759       int nbBssFiles;
760
761       if (upath[0]=='/' || upath[1] == ':' ) // ==== absolute name, load all .bbs files
762       {
763         int nbFiles = Utilities::Explore(upath, false, Filenames);
764         nbBssFiles = 0;
765         for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
766         {
767            if ((*i).substr((*i).size()-4, 4) != ".bbs")
768               continue;      // ignore non .bbs files
769            LoadScript(*i);
770            nbBssFiles++;
771         }
772         if (nbBssFiles==0)
773            bbtkMessage("Interpreter",2,
774                        "WARNING : No '.bbs' file found in [" 
775                        << upath << "]" << std::endl);
776
777         return;
778       }
779       
780
781       std::string path;
782       std::vector<std::string>::iterator i;
783       std::string fullDirectoryName;
784       for (i=script_paths.begin();i!=script_paths.end();++i)// ==== relative name, iterate + load all .bbs files
785       {
786         path = *i;
787
788        // we *really* want '.' to be the current working directory
789         if (path == ".") {
790           char buf[2048]; // for getcwd
791           char * currentDir = getcwd(buf, 2048);
792           std::string cwd(currentDir);
793           path = currentDir;
794         }
795
796         fullDirectoryName = Utilities::MakePkgnameFromPath(path, upath, false);
797
798       // Check if library exists           
799         if ( ! Utilities::IsDirectory(fullDirectoryName) )
800         {
801         // The following is *NOT* a debug time message :
802         // It's a user intended message.
803         // Please don't remove it.
804           bbtkMessage("Interpreter",1,"   [" <<fullDirectoryName 
805                       <<"] : doesn't exist" <<std::endl);
806           continue;  // try next path
807         }
808         foundFile = true;
809
810
811         int nbFiles = Utilities::Explore(fullDirectoryName, false, Filenames);
812
813         nbBssFiles = 0;
814         for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
815         {
816
817            if ((*i).substr((*i).size()-4, 4) != ".bbs")
818               continue;      // ignore non .bbs files
819            LoadScript(*i);
820            nbBssFiles++;
821         }
822         if (nbBssFiles==0)
823           bbtkMessage("Interpreter",1,
824                       "WARNING : No '.bbs' file found in [" 
825                       << fullDirectoryName << "]" << std::endl);
826            
827         //break; // a directory was found; we stop iterating
828         // LG : No! We want all files included !
829        }
830        return;
831     }
832
833     //std::string::size_type slash_position = name.find_last_of("/\\");
834
835     // if name starts with a / or a . or contains : user is assumed to have passed a relative/absolute name
836     // (not only a plain script name)
837     // we trust him, and try to expland the directory name
838     // WARNING : starting from current local directory :  ./whatYouWant  (./ mandatory!)
839
840     if (name[0]=='/' || name[1] == ':' || name[0]=='.')  // absolute path (linux/windows) or relative path
841     { 
842
843       // ===========================================================check user supplied location
844       fullnameGiven = true;
845
846       
847       fullPathScriptName =  Utilities::ExpandLibName(name, false);
848
849       // allow user to always forget ".bbs"
850       int l = fullPathScriptName.size();
851
852       if (l!=0) {
853       
854       if (l>4)
855       {
856          if (fullPathScriptName.substr(l-4, 4) != ".bbs")
857          {
858             fullPathScriptName = fullPathScriptName + ".bbs";
859          }
860       }
861       else
862       {
863          fullPathScriptName = fullPathScriptName + ".bbs";   
864       }
865
866         if ( Utilities::FileExists(fullPathScriptName))
867         {
868           foundFile = true;
869         }
870       } // endif l != 0
871     }
872     else 
873
874       // =============================================================== iterate on the paths
875       {
876       std::string path;
877       std::vector<std::string>::iterator i;
878       for (i=script_paths.begin();i!=script_paths.end();++i)
879       {
880
881         path = *i;
882        // we *really* want '.' to be the current working directory
883         if (path == ".") {
884           char buf[2048]; // for getcwd
885           char * currentDir = getcwd(buf, 2048);
886           std::string cwd(currentDir);
887           path = currentDir;
888         }
889
890        // fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true); //pkgname);
891
892             fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true);
893
894
895       // Check if library exists
896         if ( ! Utilities::FileExists(fullPathScriptName) )
897         {
898         // The following is *NOT* a debug time message :
899         // It's a user intended message.
900         // Please don't remove it.
901           bbtkMessage("Interpreter",1,
902                       "   [" <<fullPathScriptName <<"] : doesn't exist" 
903                       <<std::endl);
904           continue;  // try next path
905         }
906         bbtkMessage("Interpreter",1,
907                     "   [" <<fullPathScriptName 
908                     <<"] : found" <<std::endl);        
909         foundFile = true;
910         break; // a script was found; we stop iterating
911
912       } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
913     }
914
915     if (!foundFile)
916     {
917        if (fullnameGiven)
918          if(fullPathScriptName == "")
919             bbtkError("Path ["<<upath<<"] doesn't exist");
920          else
921             bbtkError("Script ["<<fullPathScriptName<<"] not found");
922        else
923           bbtkError("No ["<<pkgname<<".bbs] script found");
924        return;    
925     }
926     else
927        LoadScript(fullPathScriptName);
928
929     return;
930   }   
931    
932
933   //=======================================================================
934
935   void Interpreter::LoadScript( std::string fullPathScriptName)
936   {
937     if (find(mFileName.begin(),mFileName.end(),fullPathScriptName)
938         !=mFileName.end()) 
939       {
940         bbtkMessage("Interpreter",1,
941                     "file '"<<fullPathScriptName
942                     <<"' already open : do not open it once more to prevent recursive inclusion"<<std::endl);
943         return;
944       }
945
946     bbtkMessage("Interpreter",1,fullPathScriptName<<" found"<<std::endl);
947
948     std::ifstream* s;      
949     s = new std::ifstream;
950     s->open(fullPathScriptName.c_str());
951     if (!s->good()) 
952     {
953         bbtkError("Could not open file ["<<fullPathScriptName<<"]");
954         return;     
955     }
956     
957     bbtkMessage("Interpreter",1,"   -->[" << fullPathScriptName 
958                 << "] found" << std::endl);
959
960     mFile.push_back(s);
961     mFileName.push_back(fullPathScriptName);
962     mLine.push_back(0);
963     return;  
964   }
965
966   //=======================================================================
967   /**
968    *  
969    */
970   void Interpreter::CloseCurrentFile()
971   {
972     bbtkDebugMessage("Interpreter",9,"Interpreter::CloseCurrentFile()"
973                       <<std::endl);
974     
975     if (mFile.size()==0) 
976     {
977       bbtkDebugMessage("Interpreter",9," -> no file left open"<<std::endl);
978       return;
979     }
980
981     mFile.back()->close();
982     delete mFile.back();
983     mFile.pop_back();
984     bbtkDebugMessage("Interpreter",9,
985                      " Closing file '"<<mFileName.back()<<"'"<<std::endl);
986     
987     mFileName.pop_back();
988     mLine.pop_back();
989     bbtkDebugMessage("Interpreter",9," Remains "
990                      <<mFile.size()
991                      <<" open"<<std::endl);
992     bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseCurrentFile()"
993                      <<std::endl);
994   }
995   //=======================================================================
996
997  //=======================================================================
998   /**
999    *  
1000    */
1001   void Interpreter::CloseAllFiles()
1002   {
1003     bbtkDebugMessage("Interpreter",9,"Interpreter::CloseAllFiles()"
1004                       <<std::endl);
1005     
1006     while (mFile.size() != 0) 
1007     {
1008       mFile.back()->close();
1009       delete mFile.back();
1010       mFile.pop_back();
1011       bbtkDebugMessage("Interpreter",9,
1012                       " Closing file '"<<mFileName.back()<<"'"<<std::endl);
1013       mFileName.pop_back();
1014       mLine.pop_back();
1015     }
1016     bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseAllFiles()"
1017                       <<std::endl);
1018   }
1019   //=======================================================================
1020
1021
1022
1023   //=======================================================================
1024   /**
1025    *  
1026    */
1027   void Interpreter::InterpretCommand( const std::vector<std::string>& words,
1028                                       CommandInfoType& info )
1029   {
1030     bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretCommand(...)"<<std::endl);
1031     
1032     // searches the command keyword
1033     CommandDictType::iterator c;
1034     c = mCommandDict.find(words[0]);
1035     if ( c == mCommandDict.end() ) {
1036       bbtkError(words[0]<<" : unknown command");
1037     }
1038
1039     // tests the number of args 
1040     if ( ( words.size()-1 < c->second.argmin ) ||
1041          ( words.size()-1 > c->second.argmax ) )
1042     {
1043        HelpCommand(words[0]);
1044        bbtkError(words[0]<<" : wrong number of arguments");
1045     }
1046
1047     info = c->second;
1048     bbtkDecTab("Interpreter",9);
1049   }
1050   //=======================================================================
1051
1052
1053   //=======================================================================
1054   /// Displays help on all the commands
1055 void Interpreter::Help(const std::vector<std::string>& words)
1056 {
1057     unsigned int nbarg = words.size()-1;
1058     
1059     if (nbarg==0) 
1060     {
1061        HelpCommands();
1062     }
1063     else if (nbarg==1) 
1064     {
1065       if (words[1]=="packages") 
1066       {
1067          PrintPackages(true);
1068          return;
1069       }
1070       try 
1071       {
1072           HelpCommand(words[1]);
1073       }
1074       catch (bbtk::Exception e) 
1075       {
1076          try 
1077          {
1078             HelpPackage(words[1]);
1079          }
1080          catch (bbtk::Exception f) 
1081          {
1082             try 
1083             {
1084                HelpBlackBox(words[1]);
1085             }
1086            catch (bbtk::Exception g) 
1087            {
1088               try
1089               {
1090                  this->mExecuter->ShowRelations(words[1],"0","9999");
1091               }
1092               catch (bbtk::Exception h){
1093                 bbtkError("\""<<words[1].c_str()
1094                           <<"\" is not a known command, package, black box type or black box name");
1095               }
1096            }
1097          }
1098        }
1099     }
1100     else if (nbarg==2) 
1101     {
1102       if (words[2]=="all")
1103       {
1104          if ( words[1]=="packages" )
1105          {
1106             PrintPackages(true,true);
1107             return;
1108           }
1109          try 
1110          {
1111             HelpPackage(words[1],true);
1112          }
1113          catch (bbtk::Exception f) 
1114          {
1115          }
1116      }
1117      else 
1118      {
1119         HelpCommand(words[0]);
1120         bbtkError(words[0]<<" : syntax error");
1121      }
1122   }
1123   else 
1124   {
1125      bbtkError("Should not reach here !!!");
1126   }
1127 }
1128   //=======================================================================
1129
1130    //===================================================================    
1131   /// Displays the Configuration
1132   void Interpreter::Config() const
1133   {
1134     bbtkDebugMessageInc("Core",9,"Factory::Config"<<std::endl);
1135     
1136     ConfigurationFile cf = ConfigurationFile::GetInstance();
1137     
1138     const std::string config_xml_full_path      = cf.Get_config_xml_full_path();    
1139     const std::string description               = cf.Get_description();
1140     const std::string url                       = cf.Get_url();
1141     const std::string data_path                 = cf.Get_data_path();
1142     const std::string default_doc_tmp           = cf.Get_default_doc_tmp();    
1143     const std::string file_separator            = cf.Get_file_separator();    
1144     const std::vector<std::string>bbs_paths     = cf.Get_bbs_paths();
1145     const std::vector<std::string>package_paths = cf.Get_package_paths();
1146     
1147     bbtkMessage("Help",1, "============="   << std::endl);           
1148     bbtkMessage("Help",1, "Configuration"   << std::endl);
1149     bbtkMessage("Help",1, "============="   << std::endl);
1150     bbtkMessage("Help",1, "bbtk_config.xml   : [" << config_xml_full_path  << "]" << std::endl); 
1151     bbtkMessage("Help",1, "Documentation Url : [" << url             << "]" << std::endl);
1152     bbtkMessage("Help",1, "Data Path         : [" << data_path       << "]" << std::endl);
1153     bbtkMessage("Help",1, "Default Doc_tmp   : [" << default_doc_tmp << "]" << std::endl);
1154     bbtkMessage("Help",1, "File Separator    : [" << file_separator  << "]" << std::endl);
1155
1156     std::vector<std::string>::const_iterator i;
1157            
1158     bbtkMessage("Help",1, "BBS Paths   " << std::endl);     
1159     for (i = bbs_paths.begin(); i!=bbs_paths.end(); ++i )
1160     {
1161       bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1162     }    
1163     
1164     bbtkMessage("Help",1, "PACKAGE Paths : " << std::endl);     
1165     for (i = package_paths.begin(); i!=package_paths.end(); ++i )
1166     {
1167       bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1168     }
1169
1170     bbtkDebugDecTab("Core",9);
1171   }  
1172
1173   //=======================================================================
1174   /// Displays help on all the commands
1175   void Interpreter::HelpCommands()
1176   {
1177     std::cout << "Available commands :" << std::endl;
1178     CommandDictType::iterator i;
1179     for ( i =  mCommandDict.begin();
1180           i != mCommandDict.end();
1181         ++i) {
1182               std::cout << " " << i->first << std::endl;
1183       //      std::cout << "   usage : " << i->second.syntax << std::endl;
1184       //     std::cout << "    " << i->second.help << std::endl;
1185  
1186     }
1187   }
1188   //=======================================================================
1189
1190
1191   //=======================================================================
1192   /// Displays help on a particular commands
1193   void Interpreter::HelpCommand(const std::string& s)
1194   {
1195     CommandDictType::iterator c;
1196     c = mCommandDict.find(s);
1197     if ( c == mCommandDict.end() ) {
1198       bbtkError(s<<" : Unknown command");
1199     }
1200     //    std::cout << " " << s << " : "<<  std::endl;
1201     //    CommandParamDictType::iterator i;
1202     //    for ( i =  c->second.begin();
1203     //      i != c->second.end();
1204     //      ++i) {
1205     std::cout << " usage : " << c->second.syntax << std::endl;
1206     std::cout << "  " << c->second.help << std::endl;
1207     
1208   }
1209   //=======================================================================
1210
1211
1212   //=======================================================================
1213   /// Fills the vector commands with the commands which 
1214   /// have the first n chars of buf for prefix
1215   /// TODO : skip initial spaces in buf and also return the position of first
1216   /// non blank char in buf
1217   void Interpreter::FindCommandsWithPrefix( char* buf,
1218                                             int n,
1219                                             std::vector<std::string>& commands )
1220   {
1221     CommandDictType::const_iterator i;
1222     for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1223     {
1224       if ((i->first).find(buf,0,n) == 0) 
1225         commands.push_back(i->first);
1226     }
1227   }
1228   //=======================================================================
1229
1230
1231   
1232   //=======================================================================
1233 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1234   
1235   inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1236   inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1237   
1238   // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1239   // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1240   // E.G. STORE THIS IN bbtk_config.xml
1241 #define BBTK_UP_ARROW_KBCODE    0x00415B1B
1242 #define BBTK_DOWN_ARROW_KBCODE  0x00425B1B
1243 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1244 #define BBTK_LEFT_ARROW_KBCODE  0x00445B1B
1245 #define BBTK_BACKSPACE_KBCODE   0x00000008
1246 #define BBTK_DEL_KBCODE         0x0000007F
1247 #define BBTK_SPACE_KBCODE       0x00000020 
1248
1249   //=======================================================================
1250   void Interpreter::GetLineFromPrompt(std::string& s)
1251   {
1252     int c;
1253     int ind=0;
1254     
1255     int MAX_LINE_SIZE = 160;
1256     int MAX_HISTORY_SIZE = 100;
1257     
1258     char* newline = new char[MAX_LINE_SIZE];
1259     memset(newline,0,MAX_LINE_SIZE);
1260     char* histline = new char[MAX_LINE_SIZE];
1261     memset(histline,0,MAX_LINE_SIZE);
1262     
1263     char* line = newline;
1264     int hist = mHistory.size();
1265     
1266     
1267     write(1,"> ",2);
1268     while(1)
1269     {
1270        c=0;
1271        read ( STDIN_FILENO, &c, 4) ;
1272
1273        bbtkDebugMessage("Debug",9,"[0x"<<std::hex<<c<<"]\n");
1274
1275        // Printable character
1276        if ( (ind<MAX_LINE_SIZE-1) &&
1277             ( c >= BBTK_SPACE_KBCODE ) && 
1278             ( c <  BBTK_DEL_KBCODE )) 
1279        {
1280           PrintChar(c);
1281           line[ind++]=c;
1282        }
1283       // CR
1284        else if (c=='\n')
1285        {
1286        // delete the unused line
1287           if (line==newline)
1288               delete histline;
1289           else
1290               delete newline;
1291    
1292     // empty lines are not stored in from history
1293           if (strlen(line)) 
1294           {
1295              // if history too long : delete oldest command
1296              if (mHistory.size()>MAX_HISTORY_SIZE) 
1297              {
1298                 delete mHistory.front();
1299                 mHistory.pop_front();
1300              }
1301              mHistory.push_back(line);
1302           }
1303           break;
1304         }
1305        // Backspace
1306         else if ( (ind>0) && 
1307                   ((c == BBTK_BACKSPACE_KBCODE) ||
1308                    (c == BBTK_DEL_KBCODE)) )
1309           {
1310             line[ind--]=' ';
1311             BackSpace();
1312           }
1313         // Tab 
1314         else if (c=='\t')
1315           {
1316             // TODO : Command completion  
1317             std::vector<std::string> commands;
1318             FindCommandsWithPrefix( line,ind,commands);
1319             if (commands.size()==1) 
1320               {
1321                 std::string com = *commands.begin();
1322                 for (; ind<com.size(); ++ind) 
1323                   {
1324                     PrintChar(com[ind]); 
1325                     line[ind]=com[ind];
1326                   }
1327                 PrintChar(' '); 
1328                 line[ind++]=' ';
1329               }
1330             else if (commands.size()>1) 
1331               {
1332                 std::vector<std::string>::iterator i;
1333                 write(1,"\n",1);
1334                 for (i=commands.begin();i!=commands.end();++i) 
1335                   {
1336                     write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1337                     PrintChar(' ');
1338                   }
1339                 write(STDOUT_FILENO,"\n> ",3);
1340                 //for (int j=0;j<ind;++j) 
1341                   //{
1342                     write(STDOUT_FILENO,line,ind); 
1343                     //  }
1344               }
1345           }
1346         // Arrow up : back in history
1347         else if (c==BBTK_UP_ARROW_KBCODE)
1348           {
1349             if (hist) 
1350               {
1351                 // erase current line
1352                 while (ind--) BackSpace();
1353                 // 
1354                 hist--;
1355                 // 
1356                 strcpy(histline,mHistory[hist]);
1357                 line = histline;
1358                 ind = strlen(line);
1359                 
1360                 write(STDOUT_FILENO,line,ind);
1361               }
1362           }
1363         // Arrow down : down in history
1364         else if (c==BBTK_DOWN_ARROW_KBCODE)
1365           {
1366             if (hist<mHistory.size()-1) 
1367               {
1368                 // erase current line
1369                 while (ind--) BackSpace();
1370                 // 
1371                 hist++;
1372                 // 
1373                 strcpy(histline,mHistory[hist]);
1374                 line = histline;
1375                 ind = strlen(line);
1376                 
1377                 write(STDOUT_FILENO,line,ind);
1378               }
1379             // end of history : switch back to newline
1380             else if (hist==mHistory.size()-1)
1381               {
1382                 // erase current line
1383                 while (ind--) BackSpace();
1384                 // 
1385                 hist++;
1386                 // 
1387                 line = newline;
1388                 ind = strlen(line);
1389                 
1390                 write(STDOUT_FILENO,line,ind);
1391               }
1392           }
1393         // Arrow right
1394         else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1395           {
1396             PrintChar(line[ind]);
1397             ind++;
1398           }
1399
1400         // Arrow left
1401         else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1402           {
1403             PrintChar('\b');
1404             ind--;
1405     
1406           }
1407
1408       }
1409     write(STDOUT_FILENO,"\n\r",2);
1410     
1411     
1412     s = line;
1413     
1414   }
1415 #else
1416
1417   //=======================================================================
1418   void Interpreter::GetLineFromPrompt(std::string& s)
1419   {  
1420     s.clear();
1421
1422     putchar('>');
1423     putchar(' ');
1424
1425     do 
1426     {
1427       char c = getchar();
1428       if (c=='\n') 
1429       {
1430         putchar('\n');
1431         break;
1432       }
1433       if (c=='\t') 
1434       {
1435         // putchar('T');
1436         continue;
1437       }
1438       // putchar(c);
1439       s += c;
1440     } 
1441     while (true);  
1442     
1443   }
1444   //=======================================================================  
1445
1446 #endif
1447
1448
1449
1450   //=======================================================================
1451   void Interpreter::CommandLineInterpreter()
1452   {
1453     bbtkDebugMessageInc("Interpreter",9,
1454                         "Interpreter::CommandLineInterpreter()"<<std::endl);
1455     
1456 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT  
1457     // Initialise the tty in non canonical mode with no echo
1458     // oter remembers the previous settings to restore them after 
1459     struct termios ter,oter;
1460     tcgetattr(0,&ter);
1461     oter=ter;
1462     ter.c_lflag &= ~ECHO;
1463     ter.c_lflag &= ~ICANON;
1464     ter.c_cc[VMIN]=1;
1465     ter.c_cc[VTIME]=0;
1466     tcsetattr(0,TCSANOW,&ter);
1467 #endif
1468     
1469     mCommandLine = true;
1470     bool again = true;
1471     bool insideComment = false; // for multiline comment  
1472     do 
1473     {
1474       try
1475       {
1476         std::string line;
1477         GetLineFromPrompt(line);
1478         InterpretLine(line, insideComment);
1479       }
1480       catch (QuitException e)
1481       {
1482         again = false;
1483       }
1484       catch (bbtk::Exception e) 
1485       {
1486         e.Print();
1487       }
1488         catch (std::exception& e) 
1489       {
1490         std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
1491       }
1492       catch (...)
1493       {
1494         std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
1495       }
1496     }
1497     while (again);
1498   
1499 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1500     tcsetattr(0,TCSANOW,&oter);
1501 #endif
1502   
1503     std::cout << "Good bye !" << std::endl;
1504     
1505     bbtkDebugDecTab("Interpreter",9);
1506   }
1507
1508 //=======================================================================
1509 void Interpreter::Graph(const std::vector<std::string>& words)
1510 {
1511   std::string page;
1512     bool system_display = true;
1513
1514 #ifdef _USE_WXWIDGETS_
1515     if ( WxConsole::GetInstance() != 0 ) system_display = false; 
1516 #endif
1517  
1518     if (words.size()==1) 
1519     {
1520       page = mExecuter->ShowGraph(".","0","0","","","",system_display);
1521     }
1522     else if (words.size()==2) 
1523     {
1524       page = mExecuter->ShowGraph(words[1],"0","0","","","",system_display);
1525     }
1526     else if (words.size()==3) 
1527     {
1528       page = mExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
1529     }
1530     else if (words.size()==4) 
1531     {
1532       page = mExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
1533     } 
1534     else if (words.size()==5) 
1535     {
1536       page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
1537     } 
1538     else if (words.size()==6) 
1539     {
1540       page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
1541     } 
1542     else if (words.size()==7) 
1543       {
1544         page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
1545       } 
1546     
1547 #ifdef _USE_WXWIDGETS_
1548     if ( WxConsole::GetInstance() != 0 )
1549       WxConsole::GetInstance()->ShowHtmlPage(page);
1550 #endif
1551   }
1552 //=======================================================================
1553
1554
1555 //=======================================================================
1556 void  Interpreter::Index(const std::string& filename, 
1557                          const std::string& type)
1558 {
1559   Factory::IndexEntryType t;
1560   if (type=="Initials") t = Factory::Initials;
1561   else if (type=="Keywords") t = Factory::Keywords;
1562   else if (type=="Packages") t = Factory::Packages;
1563   
1564   GetGlobalFactory()->CreateHtmlIndex(t,filename);
1565 }
1566 //=======================================================================
1567
1568 }//namespace
1569
1570