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