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