]> Creatis software - bbtk.git/blob - kernel/src/bbtkInterpreter.cxx
* Fixed problem with 'include *'
[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 11:15:15 $
7   Version:   $Revision: 1.41 $
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            std::string command("include ");
799            command += *i;
800            //  LoadScript(*i,name);
801            bool tmp;
802            InterpretLine(command,tmp);
803            nbBssFiles++;
804         }
805         if (nbBssFiles==0)
806            bbtkMessage("Interpreter",2,
807                        "WARNING : No '.bbs' file found in [" 
808                        << upath << "]" << std::endl);
809         return;
810       }
811
812       std::string path;
813       std::vector<std::string>::iterator i;
814       std::string fullDirectoryName;
815       for (i=script_paths.begin();i!=script_paths.end();i++)// ==== relative name, iterate + load all .bbs files
816       {
817         path = *i;
818
819        // we *really* want '.' to be the current working directory
820         if (path == ".") {
821           char buf[2048]; // for getcwd
822           char * currentDir = getcwd(buf, 2048);
823           std::string cwd(currentDir);
824           path = currentDir;
825         }
826
827         fullDirectoryName = Utilities::MakePkgnameFromPath(path, upath, false);
828
829         //EED 18 Fev 2008
830         // without last slash "\"
831         std::string fullDirectoryNameClean = fullDirectoryName.substr(0,fullDirectoryName.size()-1);
832
833       // Check if library exists
834         if ( ! Utilities::IsDirectory( fullDirectoryNameClean ) )
835         {
836         // The following is *NOT* a debug time message :
837         // It's a user intended message.
838         // Please don't remove it.
839           bbtkMessage("Interpreter",1,"   [" <<fullDirectoryName 
840                       <<"] : doesn't exist" <<std::endl);
841           continue;  // try next path
842         }
843         foundFile = true;
844
845
846         int nbFiles = Utilities::Explore(fullDirectoryName, false, Filenames);
847
848         nbBssFiles = 0;
849         for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
850         {
851            if ((*i).substr((*i).size()-4, 4) != ".bbs")
852               continue;      // ignore non .bbs files
853            std::string command("include ");
854            command += *i;
855            bool tmp;
856            InterpretLine(command,tmp);
857            //           LoadScript(*i,name);
858            nbBssFiles++;
859         }
860         if (nbBssFiles==0)
861           bbtkMessage("Interpreter",1,
862                       "WARNING : No '.bbs' file found in [" 
863                       << fullDirectoryName << "]" << std::endl);
864
865         //break; // a directory was found; we stop iterating
866         // LG : No! We want all files included !
867        }
868        return;
869     }
870
871     //std::string::size_type slash_position = name.find_last_of("/\\");
872
873     // if name starts with a / or a . or contains : user is assumed to have passed a relative/absolute name
874     // (not only a plain script name)
875     // we trust him, and try to expland the directory name
876     // WARNING : starting from current local directory :  ./whatYouWant  (./ mandatory!)
877
878     if (name[0]=='/' || name[1] == ':' || name[0]=='.')  // absolute path (linux/windows) or relative path
879     { 
880
881       // ===========================================================check user supplied location
882       fullnameGiven = true;
883
884       fullPathScriptName =  Utilities::ExpandLibName(name, false);
885
886       // allow user to always forget ".bbs"
887       int l = fullPathScriptName.size();
888
889       if (l!=0) {
890       
891       if (l>4)
892       {
893          if (fullPathScriptName.substr(l-4, 4) != ".bbs")
894          {
895             fullPathScriptName = fullPathScriptName + ".bbs";
896          }
897       }
898       else
899       {
900          fullPathScriptName = fullPathScriptName + ".bbs";   
901       }
902
903         if ( Utilities::FileExists(fullPathScriptName))
904         {
905           foundFile = true;
906         }
907       } // endif l != 0
908     }
909     else 
910
911       // =============================================================== iterate on the paths
912       {
913       std::string path;
914       std::vector<std::string>::iterator i;
915       for (i=script_paths.begin();i!=script_paths.end();++i)
916       {
917
918         path = *i;
919        // we *really* want '.' to be the current working directory
920         if (path == ".") {
921           char buf[2048]; // for getcwd
922           char * currentDir = getcwd(buf, 2048);
923           std::string cwd(currentDir);
924           path = currentDir;
925         }
926
927        // fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true); //pkgname);
928
929             fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true);
930
931
932       // Check if library exists
933         if ( ! Utilities::FileExists(fullPathScriptName) )
934         {
935         // The following is *NOT* a debug time message :
936         // It's a user intended message.
937         // Please don't remove it.
938           bbtkMessage("Interpreter",2,
939                       "   [" <<fullPathScriptName <<"] : doesn't exist" 
940                       <<std::endl);
941           continue;  // try next path
942         }
943         bbtkMessage("Interpreter",2,
944                     "   [" <<fullPathScriptName 
945                     <<"] : found" <<std::endl);
946         foundFile = true;
947         break; // a script was found; we stop iterating
948
949       } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
950     }
951
952     if (!foundFile)
953     {
954        if (fullnameGiven)
955          if(fullPathScriptName == "")
956             bbtkError("Path ["<<upath<<"] doesn't exist");
957          else
958             bbtkError("Script ["<<fullPathScriptName<<"] not found");
959        else
960           bbtkError("No ["<<pkgname<<".bbs] script found");
961        return;
962     }
963     else
964       LoadScript(fullPathScriptName,name);
965
966     return;
967   }
968
969
970   //=======================================================================
971
972   void Interpreter::LoadScript( std::string fullPathScriptName,
973                                 std::string includeScriptName)
974   {
975     if (find(mFileName.begin(),mFileName.end(),fullPathScriptName)
976         !=mFileName.end()) 
977       {
978         bbtkMessage("Interpreter",1,"file '"<<fullPathScriptName
979                     <<"' already open : I do not open it once more to prevent recursive inclusion"<<std::endl);
980         return;
981       }
982
983     std::ifstream* s;
984     s = new std::ifstream;
985     s->open(fullPathScriptName.c_str());
986     if (!s->good()) 
987     {
988         bbtkError("Could not open file ["<<fullPathScriptName<<"]");
989         return;
990     }
991
992     bbtkMessage("Interpreter",1,"   -->[" << fullPathScriptName 
993                 << "] found" << std::endl);
994
995     mFile.push_back(s);
996     mFileName.push_back(fullPathScriptName);
997     mIncludeFileName.push_back(includeScriptName);
998     mLine.push_back(0);
999     return;
1000   }
1001
1002   //=======================================================================
1003   /**
1004    *  
1005    */
1006   void Interpreter::CloseCurrentFile()
1007   {
1008     bbtkDebugMessage("Interpreter",9,"Interpreter::CloseCurrentFile()"
1009                       <<std::endl);
1010
1011     if (mFile.size()==0)
1012     {
1013       bbtkDebugMessage("Interpreter",9," -> no file left open"<<std::endl);
1014       return;
1015     }
1016
1017     mFile.back()->close();
1018     delete mFile.back();
1019     mFile.pop_back();
1020     bbtkDebugMessage("Interpreter",9,
1021                      " Closing file '"<<mFileName.back()<<"'"<<std::endl);
1022
1023     mFileName.pop_back();
1024     mIncludeFileName.pop_back();
1025     mLine.pop_back();
1026     bbtkDebugMessage("Interpreter",9," Remains "
1027                      <<mFile.size()
1028                      <<" open"<<std::endl);
1029     bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseCurrentFile()"
1030                      <<std::endl);
1031   }
1032   //=======================================================================
1033
1034  //=======================================================================
1035   /**
1036    *  
1037    */
1038   void Interpreter::CloseAllFiles()
1039   {
1040     bbtkDebugMessage("Interpreter",9,"Interpreter::CloseAllFiles()"
1041                       <<std::endl);
1042
1043     while (mFile.size() != 0) 
1044     {
1045       mFile.back()->close();
1046       delete mFile.back();
1047       mFile.pop_back();
1048       bbtkDebugMessage("Interpreter",9,
1049                       " Closing file '"<<mFileName.back()<<"'"<<std::endl);
1050       mFileName.pop_back();
1051       mIncludeFileName.pop_back();
1052       mLine.pop_back();
1053     }
1054     bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseAllFiles()"
1055                       <<std::endl);
1056   }
1057   //=======================================================================
1058
1059
1060
1061   //=======================================================================
1062   /**
1063    *  
1064    */
1065   void Interpreter::InterpretCommand( const std::vector<std::string>& words,
1066                                       CommandInfoType& info )
1067   {
1068     bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretCommand(...)"<<std::endl);
1069
1070     // searches the command category
1071     CommandDictType::iterator c;
1072     c = mCommandDict.find(words[0]);
1073     if ( c == mCommandDict.end() ) {
1074       bbtkError(words[0]<<" : unknown command");
1075     }
1076
1077     // tests the number of args 
1078     if ( ( words.size()-1 < c->second.argmin ) ||
1079          ( words.size()-1 > c->second.argmax ) )
1080     {
1081        HelpCommand(words[0]);
1082        bbtkError(words[0]<<" : wrong number of arguments");
1083     }
1084
1085     info = c->second;
1086     bbtkDecTab("Interpreter",9);
1087   }
1088   //=======================================================================
1089
1090
1091   //=======================================================================
1092   /// Displays help on all the commands
1093 void Interpreter::Help(const std::vector<std::string>& words)
1094 {
1095     unsigned int nbarg = words.size()-1;
1096
1097     if (nbarg==0) 
1098     {
1099        HelpCommands();
1100     }
1101     else if (nbarg==1) 
1102     {
1103       if (words[1]=="packages") 
1104       {
1105          GetExecuter()->GetFactory()->PrintPackages(true);
1106          return;
1107       }
1108       try 
1109       {
1110           HelpCommand(words[1]);
1111       }
1112       catch (bbtk::Exception e) 
1113       {
1114          try 
1115          {
1116             GetExecuter()->GetFactory()->HelpPackage(words[1]);
1117 #ifdef _USE_WXWIDGETS_
1118             if ( mWxConsole != 0 )
1119               {
1120                 std::string url = 
1121                   ConfigurationFile::GetInstance().Get_doc_path();
1122                 url += "/bbdoc/" + words[1] + "/index.html";
1123                 if (Utilities::FileExists(url)) 
1124                   {
1125                     mWxConsole->ShowHtmlPage(url);
1126                   }
1127               }
1128 #endif      
1129          }
1130          catch (bbtk::Exception f) 
1131          {
1132             try 
1133             {
1134               std::string package;
1135               GetExecuter()->GetFactory()->HelpBlackBox(words[1],package);
1136 #ifdef _USE_WXWIDGETS_
1137                if ( mWxConsole != 0 )
1138                  {
1139                    std::string url = 
1140                      ConfigurationFile::GetInstance().Get_doc_path();
1141                    url += "/bbdoc/" + package + "/index.html";
1142                    if (Utilities::FileExists(url))
1143                      {
1144                        url += "#" + words[1];
1145                        mWxConsole->ShowHtmlPage(url);
1146                      }
1147                  }
1148 #endif
1149             }
1150             catch (bbtk::Exception g) 
1151               {
1152                 try
1153                   {
1154                     GetExecuter()->ShowRelations(words[1],"0","9999");
1155                   }
1156                 catch (bbtk::Exception h){
1157                   bbtkError("\""<<words[1].c_str()
1158                             <<"\" is not a known command, package, black box type or black box name");
1159                 }
1160               }
1161          }
1162       }
1163     }
1164     else if (nbarg==2) 
1165     {
1166       if (words[2]=="all")
1167       {
1168          if ( words[1]=="packages" )
1169          {
1170             GetExecuter()->GetFactory()->PrintPackages(true,true);
1171             return;
1172           }
1173          try 
1174          {
1175             GetExecuter()->GetFactory()->HelpPackage(words[1],true);
1176          }
1177          catch (bbtk::Exception f) 
1178          {
1179          }
1180      }
1181      else 
1182      {
1183         HelpCommand(words[0]);
1184         bbtkError(words[0]<<" : syntax error");
1185      }
1186   }
1187   else 
1188   {
1189      bbtkError("Should not reach here !!!");
1190   }
1191 }
1192   //=======================================================================
1193
1194    //===================================================================    
1195   /// Displays the Configuration
1196   void Interpreter::Config() const
1197   {
1198     ConfigurationFile::GetInstance().GetHelp(1);
1199   }  
1200    //===================================================================    
1201
1202   //=======================================================================
1203   /// Displays help on all the commands
1204   void Interpreter::HelpCommands()
1205   {
1206     std::cout << "Available commands :" << std::endl;
1207     CommandDictType::iterator i;
1208     for ( i =  mCommandDict.begin();
1209           i != mCommandDict.end();
1210         ++i) {
1211               std::cout << " " << i->first << std::endl;
1212       //      std::cout << "   usage : " << i->second.syntax << std::endl;
1213       //     std::cout << "    " << i->second.help << std::endl;
1214
1215     }
1216   }
1217   //=======================================================================
1218
1219
1220   //=======================================================================
1221   /// Displays help on a particular commands
1222   void Interpreter::HelpCommand(const std::string& s)
1223   {
1224     CommandDictType::iterator c;
1225     c = mCommandDict.find(s);
1226     if ( c == mCommandDict.end() ) {
1227       bbtkError(s<<" : Unknown command");
1228     }
1229     //    std::cout << " " << s << " : "<<  std::endl;
1230     //    CommandParamDictType::iterator i;
1231     //    for ( i =  c->second.begin();
1232     //      i != c->second.end();
1233     //      ++i) {
1234     std::cout << " usage : " << c->second.syntax << std::endl;
1235     std::cout << "  " << c->second.help << std::endl;
1236
1237   }
1238   //=======================================================================
1239
1240
1241   //=======================================================================
1242   /// Fills the vector commands with the commands which 
1243   /// have the first n chars of buf for prefix
1244   /// TODO : skip initial spaces in buf and also return the position of first
1245   /// non blank char in buf
1246   void Interpreter::FindCommandsWithPrefix( char* buf,
1247                                             int n,
1248                                             std::vector<std::string>& commands )
1249   {
1250     CommandDictType::const_iterator i;
1251     for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1252     {
1253       if ((i->first).find(buf,0,n) == 0) 
1254         commands.push_back(i->first);
1255     }
1256   }
1257   //=======================================================================
1258
1259
1260
1261   //=======================================================================
1262 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1263   
1264   inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1265   inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1266   
1267   // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1268   // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1269   // E.G. STORE THIS IN bbtk_config.xml
1270 #define BBTK_UP_ARROW_KBCODE    0x00415B1B
1271 #define BBTK_DOWN_ARROW_KBCODE  0x00425B1B
1272 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1273 #define BBTK_LEFT_ARROW_KBCODE  0x00445B1B
1274 #define BBTK_BACKSPACE_KBCODE   0x00000008
1275 #define BBTK_DEL_KBCODE         0x0000007F
1276 #define BBTK_SPACE_KBCODE       0x00000020 
1277
1278   //=======================================================================
1279   void Interpreter::GetLineFromPrompt(std::string& s)
1280   {
1281     int c;
1282     int ind=0;
1283
1284     int MAX_LINE_SIZE = 160;
1285     int MAX_HISTORY_SIZE = 100;
1286
1287     char* newline = new char[MAX_LINE_SIZE];
1288     memset(newline,0,MAX_LINE_SIZE);
1289     char* histline = new char[MAX_LINE_SIZE];
1290     memset(histline,0,MAX_LINE_SIZE);
1291
1292     char* line = newline;
1293     int hist = mHistory.size();
1294
1295     write(1,"> ",2);
1296     while(1)
1297     {
1298        c=0;
1299        read ( STDIN_FILENO, &c, 4) ;
1300
1301        bbtkDebugMessage("Debug",9,"[0x"<<std::hex<<c<<"]\n");
1302
1303        // Printable character
1304        if ( (ind<MAX_LINE_SIZE-1) &&
1305             ( c >= BBTK_SPACE_KBCODE ) && 
1306             ( c <  BBTK_DEL_KBCODE )) 
1307        {
1308           PrintChar(c);
1309           line[ind++]=c;
1310        }
1311       // CR
1312        else if (c=='\n')
1313        {
1314        // delete the unused line
1315           if (line==newline)
1316               delete histline;
1317           else
1318               delete newline;
1319    
1320     // empty lines are not stored in from history
1321           if (strlen(line)) 
1322           {
1323              // if history too long : delete oldest command
1324              if (mHistory.size()>MAX_HISTORY_SIZE) 
1325              {
1326                 delete mHistory.front();
1327                 mHistory.pop_front();
1328              }
1329              mHistory.push_back(line);
1330           }
1331           break;
1332         }
1333        // Backspace
1334         else if ( (ind>0) && 
1335                   ((c == BBTK_BACKSPACE_KBCODE) ||
1336                    (c == BBTK_DEL_KBCODE)) )
1337           {
1338             line[ind--]=' ';
1339             BackSpace();
1340           }
1341         // Tab 
1342         else if (c=='\t')
1343           {
1344             // TODO : Command completion  
1345             std::vector<std::string> commands;
1346             FindCommandsWithPrefix( line,ind,commands);
1347             if (commands.size()==1) 
1348               {
1349                 std::string com = *commands.begin();
1350                 for (; ind<com.size(); ++ind) 
1351                   {
1352                     PrintChar(com[ind]); 
1353                     line[ind]=com[ind];
1354                   }
1355                 PrintChar(' '); 
1356                 line[ind++]=' ';
1357               }
1358             else if (commands.size()>1) 
1359               {
1360                 std::vector<std::string>::iterator i;
1361                 write(1,"\n",1);
1362                 for (i=commands.begin();i!=commands.end();++i) 
1363                   {
1364                     write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1365                     PrintChar(' ');
1366                   }
1367                 write(STDOUT_FILENO,"\n> ",3);
1368                 //for (int j=0;j<ind;++j) 
1369                   //{
1370                     write(STDOUT_FILENO,line,ind); 
1371                     //  }
1372               }
1373           }
1374         // Arrow up : back in history
1375         else if (c==BBTK_UP_ARROW_KBCODE)
1376           {
1377             if (hist) 
1378               {
1379                 // erase current line
1380                 while (ind--) BackSpace();
1381                 // 
1382                 hist--;
1383                 // 
1384                 strcpy(histline,mHistory[hist]);
1385                 line = histline;
1386                 ind = strlen(line);
1387                 
1388                 write(STDOUT_FILENO,line,ind);
1389               }
1390           }
1391         // Arrow down : down in history
1392         else if (c==BBTK_DOWN_ARROW_KBCODE)
1393           {
1394             if (hist<mHistory.size()-1) 
1395               {
1396                 // erase current line
1397                 while (ind--) BackSpace();
1398                 // 
1399                 hist++;
1400                 // 
1401                 strcpy(histline,mHistory[hist]);
1402                 line = histline;
1403                 ind = strlen(line);
1404                 
1405                 write(STDOUT_FILENO,line,ind);
1406               }
1407             // end of history : switch back to newline
1408             else if (hist==mHistory.size()-1)
1409               {
1410                 // erase current line
1411                 while (ind--) BackSpace();
1412                 // 
1413                 hist++;
1414                 // 
1415                 line = newline;
1416                 ind = strlen(line);
1417                 
1418                 write(STDOUT_FILENO,line,ind);
1419               }
1420           }
1421         // Arrow right
1422         else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1423           {
1424             PrintChar(line[ind]);
1425             ind++;
1426           }
1427
1428         // Arrow left
1429         else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1430           {
1431             PrintChar('\b');
1432             ind--;
1433     
1434           }
1435
1436       }
1437     write(STDOUT_FILENO,"\n\r",2);
1438     
1439     
1440     s = line;
1441     
1442   }
1443 #else
1444
1445   //=======================================================================
1446   void Interpreter::GetLineFromPrompt(std::string& s)
1447   {  
1448     s.clear();
1449
1450     putchar('>');
1451     putchar(' ');
1452
1453     do 
1454     {
1455       char c = getchar();
1456       if (c=='\n') 
1457       {
1458         putchar('\n');
1459         break;
1460       }
1461       if (c=='\t') 
1462       {
1463         // putchar('T');
1464         continue;
1465       }
1466       // putchar(c);
1467       s += c;
1468     } 
1469     while (true);  
1470     
1471   }
1472   //=======================================================================  
1473
1474 #endif
1475
1476
1477
1478   //=======================================================================
1479   void Interpreter::CommandLineInterpreter()
1480   {
1481     bbtkDebugMessageInc("Interpreter",9,
1482                         "Interpreter::CommandLineInterpreter()"<<std::endl);
1483
1484 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT  
1485     // Initialise the tty in non canonical mode with no echo
1486     // oter remembers the previous settings to restore them after 
1487     struct termios ter,oter;
1488     tcgetattr(0,&ter);
1489     oter=ter;
1490     ter.c_lflag &= ~ECHO;
1491     ter.c_lflag &= ~ICANON;
1492     ter.c_cc[VMIN]=1;
1493     ter.c_cc[VTIME]=0;
1494     tcsetattr(0,TCSANOW,&ter);
1495 #endif
1496     
1497     mCommandLine = true;
1498     bool again = true;
1499     bool insideComment = false; // for multiline comment  
1500     do 
1501     {
1502       try
1503       {
1504         std::string line;
1505         GetLineFromPrompt(line);
1506         InterpretLine(line, insideComment);
1507       }
1508       catch (QuitException e)
1509       {
1510         again = false;
1511       }
1512       catch (bbtk::Exception e) 
1513       {
1514         e.Print();
1515       }
1516         catch (std::exception& e) 
1517       {
1518         std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
1519       }
1520       catch (...)
1521       {
1522         std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
1523       }
1524     }
1525     while (again);
1526
1527 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1528     tcsetattr(0,TCSANOW,&oter);
1529 #endif
1530
1531     std::cout << "Good bye !" << std::endl;
1532
1533     bbtkDebugDecTab("Interpreter",9);
1534   }
1535
1536 //=======================================================================
1537 void Interpreter::Graph(const std::vector<std::string>& words)
1538 {
1539   std::string page;
1540     bool system_display = true;
1541
1542 #ifdef _USE_WXWIDGETS_
1543     if ( mWxConsole != 0 ) system_display = false; 
1544 #endif
1545  
1546     if (words.size()==1) 
1547     {
1548       page = mExecuter->ShowGraph(".","0","0","","","",system_display);
1549     }
1550     else if (words.size()==2) 
1551     {
1552       page = mExecuter->ShowGraph(words[1],"0","0","","","",system_display);
1553     }
1554     else if (words.size()==3) 
1555     {
1556       page = mExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
1557     }
1558     else if (words.size()==4) 
1559     {
1560       page = mExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
1561     } 
1562     else if (words.size()==5) 
1563     {
1564       page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
1565     } 
1566     else if (words.size()==6) 
1567     {
1568       page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
1569     } 
1570     else if (words.size()==7) 
1571       {
1572         page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
1573       } 
1574     
1575 #ifdef _USE_WXWIDGETS_
1576     if ( mWxConsole != 0 )
1577       mWxConsole->ShowHtmlPage(page);
1578 #endif
1579   }
1580 //=======================================================================
1581
1582
1583 //=======================================================================
1584 void  Interpreter::Index(const std::string& filename, 
1585                          const std::string& type)
1586 {
1587   Factory::IndexEntryType t;
1588   if (type=="Initials") t = Factory::Initials;
1589   else if (type=="Categories") t = Factory::Categories;
1590   else if (type=="Packages") t = Factory::Packages;
1591   else if (type=="Adaptors") t = Factory::Adaptors;
1592   
1593   GetExecuter()->GetFactory()->CreateHtmlIndex(t,filename);
1594 }
1595 //=======================================================================
1596
1597 }//namespace
1598
1599