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