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