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