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