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