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