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