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