]> Creatis software - bbtk.git/blob - kernel/src/bbtkInterpreterVirtual.cxx
#3073 BBTK Bug New Normal - message documentation in boxes
[bbtk.git] / kernel / src / bbtkInterpreterVirtual.cxx
1 /*
2  # ---------------------------------------------------------------------
3  #
4  # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image
5  #                        pour la SantÈ)
6  # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton
7  # Previous Authors : Laurent Guigues, Jean-Pierre Roux
8  # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil
9  #
10  #  This software is governed by the CeCILL-B license under French law and
11  #  abiding by the rules of distribution of free software. You can  use,
12  #  modify and/ or redistribute the software under the terms of the CeCILL-B
13  #  license as circulated by CEA, CNRS and INRIA at the following URL
14  #  http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
15  #  or in the file LICENSE.txt.
16  #
17  #  As a counterpart to the access to the source code and  rights to copy,
18  #  modify and redistribute granted by the license, users are provided only
19  #  with a limited warranty  and the software's author,  the holder of the
20  #  economic rights,  and the successive licensors  have only  limited
21  #  liability.
22  #
23  #  The fact that you are presently reading this means that you have had
24  #  knowledge of the CeCILL-B license and that you accept its terms.
25  # ------------------------------------------------------------------------ */
26
27
28 /*=========================================================================
29   Program:   bbtk
30   Module:    $RCSfile: bbtkInterpreter.cxx,v $
31   Language:  C++
32   Date:      $Date: 2010/09/14 07:18:46 $
33   Version:   $Revision: 1.88 $
34 =========================================================================*/
35
36
37
38 /**
39  *  \file 
40  *  \brief class Interpreter :
41  */
42
43 #include "bbtkInterpreterVirtual.h"
44 //#include "bbtkTranscriptor.h"
45 #include "bbtkConfigurationFile.h"
46 #include "bbtkUtilities.h"
47 //#include "bbtkAtomicBlackBox.h"
48 //#include "bbtkWxBlackBox.h"
49 #include <sys/stat.h>
50 #include <algorithm>
51 #ifdef CMAKE_HAVE_TERMIOS_H
52 #include <termios.h>
53 #define BBTK_USE_TERMIOS_BASED_PROMPT
54 #endif
55
56 #include <string>
57
58 namespace bbtk
59 {
60
61  //=======================================================================
62         InterpreterVirtual::Pointer InterpreterVirtual::New() 
63   {
64     bbtkDebugMessage("kernel",9,"InterpreterVirtual::New()"<<std::endl);
65     return MakePointer( new InterpreterVirtual() );
66   }
67  //=======================================================================
68
69  //=======================================================================
70   InterpreterVirtual::InterpreterVirtual() 
71   {
72     Init();
73   }
74   //=======================================================================
75
76
77   //=======================================================================
78   void InterpreterVirtual::Init() 
79   {
80     mUser                       = 0;
81     mCommandLine        = false;
82     mThrow                      = false;
83     bufferNb            = 0;  
84     bbtk::MessageManager::RegisterMessageType("echo","Level>0 : Prints the output of the 'print' commands of the user.\n\tLevel>1 : Prints the command being interpreted",1);
85     bbtk::MessageManager::RegisterMessageType("Interpreter","Messages of the interpreter",0);
86     bbtkDebugMessageInc("Interpreter",9,"InterpreterVirtual::Interpreter()" <<std::endl);
87
88     // For the time being, comment out previous line, and
89     // uncomment next line to check Transcriptor
90
91     //mVirtualExecuter = new bbtk::Transcriptor("GeneratedProgram.txt");
92
93     // Builds the commands dict
94     CommandInfoType info;
95    
96     info.keyword = "new";
97     info.argmin = 2;
98     info.argmax = 2;
99     info.code = cNew;
100     info.syntax = "new <type> <name>";
101     info.help = "Creates a new black box of type <type> with name <name>";
102     mCommandDict[info.keyword] = info;
103     
104     info.keyword = "delete";
105     info.argmin = 1;
106     info.argmax = 1;
107     info.code = cDelete;
108     info.syntax = "delete <box>";
109     info.help = "Deletes the black box of name <box>";
110     mCommandDict[info.keyword] = info;
111
112     info.keyword = "clear";
113     info.argmin = 0;
114     info.argmax = 0;
115     info.code = cClear;
116     info.syntax = "clear";
117     info.help = "Clears the currently defined complex box (deletes all its boxes and connections)";
118     mCommandDict[info.keyword] = info;
119
120     info.keyword = "break";
121     info.argmin = 0;
122     info.argmax = 0;
123     info.code = cBreak;
124     info.syntax = "break";
125     info.help = "Breaks the current execution";
126     mCommandDict[info.keyword] = info;
127
128     info.keyword = "newgui";
129     info.argmin = 2;
130     info.argmax = 2;
131     info.code = cNewGUI;
132     info.syntax = "newgui <box> <name>";
133     info.help = "Automatically creates a graphical user interface with name <name> for the black box <box> and connects it to the box inputs";
134     mCommandDict[info.keyword] = info;
135
136     info.keyword = "connect";
137     info.argmin = 2;
138     info.argmax = 2;
139     info.code = cConnect;
140     info.syntax = "connect <box1.output> <box2.input>";
141     info.help = "Connects the ouput <output> of black box <box1> to the input <input> of black box <box2>";
142     mCommandDict[info.keyword] = info;
143
144     info.keyword = "print";
145     info.argmin = 1;
146     info.argmax = 1;
147     info.code = cPrint;
148     info.syntax = "print <string>";
149     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').";
150     mCommandDict[info.keyword] = info;
151
152     info.keyword = "exec";
153     info.argmin = 1;
154     info.argmax = 2;
155     info.code = cExec;
156     info.syntax = "exec <box | 'freeze' | 'unfreeze' | 'freeze_no_error' >";
157     info.help = "Executes the black box of name <box> (and connected boxes if needed). If the special keyword 'freeze' is given then freezes any further execution command. 'unfreeze' reverts to normal execution mode. 'freeze_no_error' is like freeze but also skips any error.";
158     mCommandDict[info.keyword] = info;
159
160     info.keyword = "package";
161     info.argmin = 1;
162     info.argmax = 1;
163     info.code = cPackage;
164     info.syntax = "package <name>";
165     info.help = "Begins the definition of a package.";
166     mCommandDict[info.keyword] = info;
167     
168     info.keyword = "endpackage";
169     info.argmin = 0;
170     info.argmax = 0;
171     info.code = cEndPackage;
172     info.syntax = "endpackage";
173     info.help = "Ends the definition of a package.";
174     mCommandDict[info.keyword] = info;
175
176     info.keyword = "define";
177     info.argmin = 1;
178     info.argmax = 2;
179     info.code = cDefine;
180     info.syntax = "define <type> [<package>]";
181     info.help = "Begins the definition of a new type of complex black box called <type>. If <package> is provided will create it in the given package.";
182     mCommandDict[info.keyword] = info;
183     
184     info.keyword = "endefine";
185     info.argmin = 0;
186     info.argmax = 0;
187     info.code = cEndDefine;
188     info.syntax = "endefine";
189     info.help = "Ends the definition of a new type of complex black box";
190     mCommandDict[info.keyword] = info;
191
192     info.keyword = "kind";
193     info.argmin = 1;
194     info.argmax = 1;
195     info.code = cKind;
196     info.syntax = "kind <ADAPTOR|DEFAULT_ADAPTOR|GUI|DEFAULT_GUI>";
197     info.help = "Sets the kind of the currently defined complex black box";
198     mCommandDict[info.keyword] = info;
199
200     info.keyword = "input";
201     info.argmin = 3;
202     info.argmax = 3;
203     info.code = cInput;
204     info.syntax = "input <name> <box.input> <help>";
205     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";
206     mCommandDict[info.keyword] = info;
207
208     info.keyword = "output";
209     info.argmin = 3;
210     info.argmax = 3;
211     info.code = cOutput;
212     info.syntax = "output <name> <box.output> <help>";
213     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";
214     mCommandDict[info.keyword] = info;
215
216     info.keyword = "set";
217     info.argmin = 2;
218     info.argmax = 2;
219     info.code = cSet;
220     info.syntax = "set <box.input> <value>";
221     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";
222     mCommandDict[info.keyword] = info;
223    
224     info.keyword = "config";  // JPR
225     info.argmin = 0;
226     info.argmax = 0;
227     info.code = cConfig;
228     info.syntax = "config";
229     info.help = "Prints the value of all configuration parameters";
230     mCommandDict[info.keyword] = info;
231
232     info.keyword = "index";  // LG
233     info.argmin = 0;
234     info.argmax = 2;
235     info.code = cIndex;
236
237     info.syntax = "index [<filename> ['Initials'(default)|'Packages'|'Categories'|'Adaptors']]";
238     info.help = "Creates an html index of known boxes. If filename is provided then save it to the file 'filename'. The default index entries are the initial letters of the names of the boxes. If 'Packages' or 'Categories' is provided then the entries are either the packages names or the categories. If 'Adaptors' is provided then an alphabetical index of all adaptors is created.";
239     mCommandDict[info.keyword] = info;
240
241     info.keyword = "reset";  
242     info.argmin = 0;
243     info.argmax = 0;
244     info.code = cReset;
245     info.syntax = "reset";
246     info.help = "Deletes all boxes and unloads all packages (reset to start state)";
247     mCommandDict[info.keyword] = info;
248
249     info.keyword = "author";
250     info.argmin = 1;
251     info.argmax = 1;
252     info.code = cAuthor;
253     info.syntax = "author <string>";
254     info.help = "Adds the string <string> to the author information of the black box being defined";
255     mCommandDict[info.keyword] = info;
256     
257     info.keyword = "category"; //JP
258     info.argmin = 1;
259     info.argmax = 1;
260     info.code = cCategory;
261     info.syntax = "category <list of items, separated by ;>";
262     info.help = "Adds the string <string> to the category information of the black box being defined";
263     mCommandDict[info.keyword] = info;
264
265     info.keyword = "description";
266     info.argmin = 1;
267     info.argmax = 1;
268     info.code = cDescription;
269     info.syntax = "description <string>";
270     info.help = "Adds the string <string> to the descriptive information of the black box being defined";
271     mCommandDict[info.keyword] = info;
272
273     info.keyword = "help";
274     info.argmin = 0;
275     info.argmax = 2;
276     info.code = cHelp;
277     info.syntax = "help";
278     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>";
279     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.";
280     mCommandDict[info.keyword] = info;
281
282     info.keyword = "message";
283     info.argmin = 0;
284     info.argmax = 2;
285     info.code = cMessage;
286     info.syntax = "message <kind> <level>";
287     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.";  
288     mCommandDict[info.keyword] = info;
289
290     info.keyword = "include";
291     info.argmin = 1;
292     info.argmax = 2;
293     info.code = cInclude;
294     info.syntax = "include <filename> [source]";
295     info.help = "Includes the file <filename>.\n  'source' : If the keyword 'source' is provided then informs the interpreter 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).";
296     mCommandDict[info.keyword] = info;
297
298     info.keyword = "quit";
299     info.argmin = 0;
300     info.argmax = 0;
301     info.code = cQuit;
302     info.syntax = "quit";
303     info.help = "Quits the program (during script execution it stops the complete execution)";
304     mCommandDict[info.keyword] = info;
305
306     info.keyword = "load";
307     info.argmin = 1;
308     info.argmax = 1;
309     info.code = cLoad;
310     info.syntax = "load <packagename>";
311     info.help = "Loads the black box package <packagename>";
312     mCommandDict[info.keyword] = info;
313
314     info.keyword = "unload";
315     info.argmin = 1;
316     info.argmax = 1;
317     info.code = cUnload;
318     info.syntax = "unload <packagename>";
319     info.help = "Unloads the black box package <packagename>";
320     mCommandDict[info.keyword] = info;
321
322     info.keyword = "graph";
323     info.argmin = 0;
324     info.argmax = 6;
325     info.code = cGraph;
326     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 ]]]]]]";
327     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')";
328     mCommandDict[info.keyword] = info;
329
330     info.keyword = "debug";
331     info.argmin = 0;
332     info.argmax = 1;
333     info.code = cDebug;
334     info.syntax = "debug [expr|-C|-D]";
335     info.help = "Prints debug info on living bbtk objects containing the string 'expr' (default expr=''). -C checks the factory integrity. -D turns on objects debug info after main ends";
336     mCommandDict[info.keyword] = info;
337
338     /*
339     info.keyword = "workspace";
340     info.argmin = 1;
341     info.argmax = 2;
342     info.code = cWorkspace;
343     info.syntax = "workspace < ( freeze | unfreeze ) | ( rename <newname> ) >";
344     info.help = "Configures the workspace.\n        'freeze' allows 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.";
345     mCommandDict[info.keyword] = info;
346     */
347
348
349   } 
350   //=======================================================================
351   
352   
353   
354   //=======================================================================  
355   /**
356    *  
357    */
358   InterpreterVirtual::~InterpreterVirtual()
359   {
360     bbtkDebugMessage("object",2,"==> ~Interpreter()" <<std::endl);
361   }
362   //=======================================================================
363
364
365   //=======================================================================
366   InterpreterException::InterpreterException( const std::string& message,
367                                       bool in_script_file,
368                                       const std::string& script_file,
369                                       int script_line 
370                                       )
371     : Exception("interpreter",0,message),
372       mInScriptFile(in_script_file),
373       mScriptFile(script_file),
374       mScriptLine(script_line)
375   {
376   }
377   //=======================================================================
378   //=======================================================================
379   InterpreterException::InterpreterException( const Exception& excep,
380                       bool in_script_file,
381                       const std::string& script_file,
382                       int script_line 
383                       )
384     : Exception(excep),
385       mInScriptFile(in_script_file),
386       mScriptFile(script_file),
387       mScriptLine(script_line)
388   {
389   }
390   //=======================================================================
391
392
393   //=======================================================================
394   void InterpreterVirtual::CatchInterpreterException( const InterpreterException& e )
395   {
396 //EED Borrame     if (GetExecuter()->GetNoErrorMode()) 
397 //EED Borrame       {
398 //EED Borrame         bbtkWarning("ERROR :"<<e.GetErrorMessage()
399 //EED Borrame               <<" ("<<e.GetScriptFile()<<":"<<e.GetScriptLine()
400 //EED Borrame               <<" skipped");
401 //EED Borrame   return;
402 //EED Borrame       }
403           if (mThrow) 
404       {
405                   if (e.GetErrorMessage()!="break")
406                   {
407                           mStatus = Interpreter_ERROR;         
408                           CloseAllFiles();
409                   }
410                   throw InterpreterException(e);
411       } else {
412                   std::stringstream mess;
413                   mess << "* ERROR : "<<e.GetErrorMessage()<<std::endl;
414                   if (e.IsInScriptFile())
415                   {
416                           mess << "* FILE  : \""<<e.GetScriptFile()<<"\""<<std::endl;
417                           mess << "* LINE  : "<<e.GetScriptLine()<<std::endl;
418                   }
419                   CloseAllFiles();
420                   std::cerr << mess.str();
421       } // if
422   }
423   //=======================================================================
424
425   //=======================================================================
426   void InterpreterVirtual::CatchBbtkException( const bbtk::Exception& e )
427   {
428 //EED Borrame     if (GetExecuter()->GetNoErrorMode()) 
429 //EED Borrame       {
430 //EED Borrame   std::string file("?");
431 //EED Borrame   int line = 0;
432 //EED Borrame   if (mFileName.size()) {
433 //EED Borrame     file = mFileName.back();
434 //EED Borrame     line = mLine.back();
435 //EED Borrame   }    
436 //EED Borrame   bbtkWarning("ERROR '"<<e.GetErrorMessage()
437 //EED Borrame               <<"' ("<<file<<":"<<line<<") skipped");
438 //EED Borrame   return;
439 //EED Borrame      }
440           
441     mStatus = Interpreter_ERROR;               
442     if (mThrow) 
443         {
444                 bool in_script = false;
445                 std::string file("");
446                 int line = 0;
447                 if (mFileName.size()) 
448                 {
449                         std::ifstream* fs = dynamic_cast<std::ifstream*>(mFile.back());
450                         if (fs!=0) in_script = true;      
451                         file = mFileName.back();
452                         line = mLine.back();
453                 }   
454                 if (e.GetErrorMessage()!="break")
455                         CloseAllFiles();
456                 throw InterpreterException(e,in_script,file,line);
457         } else {
458                 std::stringstream mess;
459                 mess << "* ERROR : "<<e.GetErrorMessage()<<std::endl;
460                 if (mFileName.size()) 
461                 {
462                         mess << "* FILE  : \""<<mFileName.back()<<"\""<<std::endl;
463                         mess << "* LINE  : "<<mLine.back()<<std::endl;
464                 }    
465                 CloseAllFiles();
466                 std::cerr << mess.str();
467         } // if
468   }
469   //=======================================================================
470   
471   //=======================================================================
472   void InterpreterVirtual::CatchStdException( const std::exception& e )
473   {  
474 //EED Borrame   if (GetExecuter()->GetNoErrorMode()) 
475 //EED Borrame      {
476 //EED Borrame   std::string file("?");
477 //EED Borrame   int line = 0;
478 //EED Borrame   if (mFileName.size()) {
479 //EED Borrame     file = mFileName.back();
480 //EED Borrame     line = mLine.back();
481 //EED Borrame   }    
482 //EED Borrame   bbtkWarning("ERROR '"<<e.what()
483 //EED Borrame               <<"' ("<<file<<":"<<line<<") skipped");
484 //EED Borrame   return;
485 //EED Borrame      }
486           
487     mStatus = Interpreter_ERROR;               
488         if (mThrow) 
489         {
490                 bool in_script = false;
491                 std::string file("");
492                 int line = 0;
493                 if (mFileName.size()) {
494                         std::ifstream* fs = dynamic_cast<std::ifstream*>(mFile.back());
495                         if (fs!=0) in_script = true;      
496                         file = mFileName.back();
497                         line = mLine.back();
498                 }    
499                 CloseAllFiles();
500                 throw InterpreterException(e.what(),in_script,file,line);
501         } else {
502                 std::stringstream mess;
503                 mess << "* ERROR : "<<e.what()<<std::endl;
504                 if (mFileName.size()) 
505                 {
506                         mess << "* FILE  : \""<<mFileName.back()<<"\""<<std::endl;
507                         mess << "* LINE  : "<<mLine.back()<<std::endl;
508                 }    
509                 CloseAllFiles();
510                 std::cerr << mess.str();
511         }
512   }
513         
514   //=======================================================================
515
516   //=======================================================================
517   void InterpreterVirtual::CatchUnknownException()
518   {
519 //EED Borrame   if (GetExecuter()->GetNoErrorMode()) 
520 //EED Borrame       {
521 //EED Borrame   std::string file("?");
522 //EED Borrame   int line = 0;
523 //EED Borrame   if (mFileName.size()) {
524 //EED Borrame     file = mFileName.back();
525 //EED Borrame     line = mLine.back();
526 //EED Borrame   }
527 //EED Borrame           bbtkWarning("UNDEFINED ERROR "
528 //EED Borrame                       <<"("<<file<<":"<<line<<") skipped");
529 //EED Borrame           return;
530 //EED Borrame         }
531     mStatus = Interpreter_ERROR;               
532     if (mThrow) 
533       {
534         bool in_script = false;
535         std::string file("");
536         int line = 0;
537         if (mFileName.size()) {
538           std::ifstream* fs = dynamic_cast<std::ifstream*>(mFile.back());
539           if (fs!=0) in_script = true;    
540           file = mFileName.back();
541           line = mLine.back();
542         }    
543         CloseAllFiles();
544         throw InterpreterException("Unknown exception caught",
545                                    in_script,file,line);
546       }
547     else
548       {
549         std::stringstream mess;
550         mess << "* UNDEFINED ERROR (not a bbtk nor a std exception)" 
551              << std::endl;
552         if (mFileName.size()) {
553           mess << "* FILE  : \""<<mFileName.back()<<"\""<<std::endl;
554           mess << "* LINE  : "<<mLine.back()<<std::endl;
555         }    
556         CloseAllFiles();
557         std::cerr << mess.str();
558       }
559   }
560   //=======================================================================
561
562   //=======================================================================
563   
564 #define CATCH_MACRO                                     \
565   catch (InterpreterException e)                        \
566     {                                                   \
567       CatchInterpreterException(e);                     \
568     }                                                   \
569   catch (bbtk::Exception e)                             \
570     {                                                   \
571       CatchBbtkException(e);                            \
572     }                                                   \
573   catch (std::exception& e)                             \
574     {                                                   \
575       CatchStdException(e);                             \
576     }                                                   \
577   catch (...)                                           \
578     {                                                   \
579       CatchUnknownException();                          \
580     }                                           
581   //=======================================================================
582    
583
584   //=======================================================================
585   InterpreterVirtual::ExitStatus InterpreterVirtual::InterpretFile( const std::string& filename, bool source )
586   {
587           bbtkDebugMessage("interpreter",4,"==> InterpreterVirtual::InterpretFile(\""<<filename<<"\")"<<std::endl);
588
589     bool exm = mCommandLine;
590     mCommandLine = false;
591
592     try 
593     {
594       mStatus = Interpreter_OK;
595       SwitchToFile(filename,source);
596       mInsideComment = false;
597       InterpretCurrentStreams();
598     } 
599     CATCH_MACRO;
600     
601     bbtkDebugMessage("interpreter",4,
602                      "<== InterpreterVirtual::InterpretFile(\""
603                      <<filename<<"\")"<<std::endl);
604
605
606     mCommandLine = exm;
607
608     return mStatus;
609   }
610   //=======================================================================
611
612
613   //=======================================================================
614   InterpreterVirtual::ExitStatus 
615   InterpreterVirtual::InterpretBuffer( std::stringstream* buffer )
616   {
617     bbtkDebugMessage("interpreter",4,"==> InterpreterVirtual::InterpretBuffer()"<<std::endl);
618
619     bool exm = mCommandLine;
620     mCommandLine = false;
621
622     try 
623     {
624       mStatus = Interpreter_OK;
625       SwitchToStream(buffer);
626       mInsideComment = false;
627       InterpretCurrentStreams();
628     }
629     CATCH_MACRO;
630     
631     //    CloseAllFiles();
632     bbtkDebugMessage("interpreter",4,"<== InterpreterVirtual::InterpretBuffer()"<<std::endl);
633
634     
635     mCommandLine = exm;
636     return mStatus;
637   }
638   //=======================================================================
639
640   //=======================================================================
641   /// Interprets the currently open streams
642   InterpreterVirtual::ExitStatus InterpreterVirtual::InterpretCurrentStreams()
643   {
644     bbtkDebugMessage("interpreter",4,
645                      "==> InterpreterVirtual::InterpretCurrentStreams()"<<std::endl);
646
647     while (mFile.size()>0) 
648       {
649         while (!mFile.back()->eof()) {
650           mLine.back()++;
651           char buf[500];
652           mFile.back()->getline(buf,500);
653           std::string str(buf);
654           //size 0 JCP 21-09-2009
655           int size=str.length();
656           if(size != 0){
657                   if ( str[ size-1 ]==13  )
658             {
659               str.erase(size-1,1);
660             }
661                   try
662                         {
663                           DoInterpretLine(str);
664                         }
665                   CATCH_MACRO;
666           }
667           
668         } 
669         CloseCurrentFile();
670       }
671     bbtkDebugMessage("interpreter",4,
672                      "<== InterpreterVirtual::InterpretCurrentStreams()"<<std::endl);
673
674     return mStatus;
675   }
676   //=======================================================================
677
678   //=======================================================================
679   /// Runs the interpretation of a command
680   InterpreterVirtual::ExitStatus InterpreterVirtual::InterpretLine( const std::string& line )
681   {
682     bbtkDebugMessage("interpreter",5,"==> InterpreterVirtual::InterpretLine('"<<line<<"')"<<std::endl);
683
684     try 
685     {
686       mStatus = Interpreter_OK;
687       mInsideComment = false;
688 //std::cout<<"JCP bbtkInterpreter.cxx InterpreterVirtual::InterpretLine("<<std::endl;
689       DoInterpretLine(line );
690     }
691     CATCH_MACRO;
692     
693     
694    bbtkDebugMessage("interpreter",5,"<== InterpreterVirtual::InterpretLine('"<<line<<"')"<<std::endl);
695     
696     return mStatus;
697   }
698   //=======================================================================  
699   
700         void InterpreterVirtual::commandNew(const std::string &boxType, const std::string &boxName) // virtual 
701     {
702     }
703         
704         void InterpreterVirtual::commandDelete(const std::string &boxName)
705     {
706     }
707
708         void InterpreterVirtual::commandConnection(const std::string &nodeFrom,const std::string &outputLabel,const std::string &nodeTo,const std::string &inputLabel)
709     {
710     }
711                 
712         void InterpreterVirtual::commandPackage(const std::string &packageName)
713     {
714     }
715         
716         void InterpreterVirtual::commandEndPackage()
717     {
718     }
719         
720         void InterpreterVirtual::commandDefine(const std::string &name,const std::string &pack,const std::string &scriptfilename)
721     {
722     }
723
724         void InterpreterVirtual::commandEndDefine()
725     {
726     }
727
728         void InterpreterVirtual::commandKind(const std::string &kind)
729     {
730     }
731         
732         void InterpreterVirtual::commandPrint(const std::string &value)
733     {
734     }
735         
736         
737         void InterpreterVirtual::commandExec(const std::string &word)
738     {
739     }
740         
741         
742         void InterpreterVirtual::commandInput(const std::string &name,const std::string &box,const std::string &input,const std::string  &help)
743     {
744     }
745         
746         void InterpreterVirtual::commandOutput(const std::string &name,const std::string &box,const std::string &output,const std::string  &help)
747     {
748     }
749         
750         void InterpreterVirtual::commandSet(const std::string &box,const std::string &input,const std::string &value)
751     {
752     }
753
754         void InterpreterVirtual::commandAuthor(const std::string &author)
755     {
756     }
757
758         void InterpreterVirtual::commandCategory(const std::string &categorytype)
759     {
760     }
761         
762         
763         
764         void InterpreterVirtual::commandDescription(const std::string &description)
765     {
766     }
767
768         
769         void InterpreterVirtual::commandClear()
770     {
771     }
772         
773         void InterpreterVirtual::commandInclude(const std::string &word, bool ok)
774     {
775     }
776         
777         
778         void InterpreterVirtual::commandLoad(const std::string &packageName)
779     {
780     }
781
782         void InterpreterVirtual::commandUnload(const std::string &packageName)
783     {
784     }
785         
786         void InterpreterVirtual::commandBreak()
787     {
788     }
789         
790         void InterpreterVirtual::commandQuit()
791     {
792     }
793         
794         void InterpreterVirtual::commandMessage()
795     {
796     }
797         
798         void InterpreterVirtual::commandMessage(const std::string &kind,const std::string &levelstr)
799     {
800     }
801         
802         
803         
804   //=======================================================================  
805   void InterpreterVirtual::DoInterpretLine( const std::string& line )
806   {  
807     bbtkDebugMessage("interpreter",6,"==> InterpreterVirtual::DoInterpretLine(\""
808                      <<line<<"\")"<<std::endl);
809     std::vector<std::string> words;
810     SplitLine(line,words);
811
812           
813           
814     // Empty line
815     if (words.size()<1) 
816     {
817        bbtkDebugDecTab("interpreter",9);
818        return;
819     }
820
821     // Single line comment : # or //
822     if ( words[0][0]=='#' || (words[0][0]=='/' && words[0][1]=='/') ) 
823     {  
824        bbtkDebugDecTab("interpreter",9);
825        bbtkMessage("interpreter",9,"Comment"<<std::endl);
826        return;
827     }
828
829     // Multi line comment ( /* ... */ ) -delimiters on different lines !-
830     
831     if (words[0][0]=='/' && words[0][1]=='*') 
832     {  
833        bbtkDebugDecTab("interpreter",9);
834        bbtkMessage("interpreter",9,"In multiline comment"<<std::endl);
835        mInsideComment = true;
836        return;
837     }
838
839     if (words[0][0]=='*' && words[0][1]=='/') 
840     {  
841        bbtkDebugDecTab("interpreter",9);
842        bbtkMessage("interpreter",9,"Out multiline comment"<<std::endl);
843        if ( !mInsideComment ) {
844           bbtkDebugDecTab("interpreter",9);
845           bbtkMessage("interpreter",9,"Comment mismatch : '*/' with no matching '/*'"<<std::endl);       
846        }
847        mInsideComment = false;
848        return;
849     }
850
851     if (mInsideComment) 
852     {  
853        bbtkDebugDecTab("interpreter",9);
854        bbtkMessage("interpreter",9,"Multiline Comment"<<std::endl);
855        return;
856     }
857           
858
859     // Command 
860     CommandInfoType command;
861     InterpretCommand(words,command);
862 //std::cout<<"JCP bbtkInterpreter command.keyword ="<<command.keyword<<std::endl;
863     bbtkDebugMessage("interpreter",9,
864                      "Command='"<<command.keyword
865                       <<"' code="<<command.code<<std::endl); 
866           
867     std::string left,right,left2,right2;
868     std::string filename;
869
870     // message command
871     if (command.code==cMessage)
872       {
873         if (words.size()<3)
874           {
875                   commandMessage();
876 //EED Borrame       mVirtualExecuter->HelpMessages();
877           }
878         else
879           {
880                 commandMessage(words[1],words[2]);
881 //EED Borrame           sscanf(words[2].c_str(),"%d",&level);
882 //EED Borrame       mVirtualExecuter->SetMessageLevel(words[1],level);
883           }
884         return;
885       }
886     else 
887       {
888         bbtkMessage("echo",2,line<<std::endl);
889       }
890
891     // break and quit commands
892     if ((command.code==cBreak) || (command.code==cQuit))
893     {
894 //EED-Borrame   bool in_script = false;
895 //EED-Borrame   std::string file("");
896 //EED-Borrame   int line = 0;
897
898 //EED-Borrame   if (mFileName.size()) 
899 //EED-Borrame     {
900 //EED-Borrame       std::ifstream* fs = dynamic_cast<std::ifstream*>(mFile.back());
901 //EED-Borrame       if (fs!=0) in_script = true;          
902 //EED-Borrame       file = mFileName.back();
903 //EED-Borrame       line = mLine.back();
904 //EED-Borrame     } 
905           if (command.code==cBreak)
906           {
907             /*
908             std::cout << "BreakException(" 
909                       <<in_script<<","
910                       <<file<<","
911                       <<line<<")"<<std::endl;
912             */
913                   commandBreak();
914 //EED Borrame       bbtkError("break");//,in_script,file,line);
915             //      throw BreakException(in_script,file,line);
916           } else {
917                   commandQuit();
918 //EED Borrame       bbtkError("quit");//,in_script,file,line);
919               //throw QuitException(in_script,file,line);
920           } // cBreak
921           return;
922    } // cBreak  cQuit  
923 //std::cout<<" mVirtualExecuter->Create(words[1],words[2]); "<<line<<std::endl;
924     // other cammands
925
926           
927     switch (command.code) 
928       {
929       case cNew :
930                 commandNew(words[1],words[2]);
931 //EED Borrame        mVirtualExecuter->Create(words[1],words[2]);
932         break;
933
934       case cDelete :
935                           commandDelete(words[1]);
936 //EED Borrame   mVirtualExecuter->Destroy(words[1]);
937         break;
938
939       case cConnect :
940         Utilities::SplitAroundFirstDot(words[1],left,right);
941         Utilities::SplitAroundFirstDot(words[2],left2,right2);      
942         commandConnection(left,right,left2,right2);
943 //EED Borrame        mVirtualExecuter->Connect(left,right,left2,right2);
944         break;
945
946       case cPackage :
947                           commandPackage(words[1]);
948 //EED Borrame                mVirtualExecuter->BeginPackage(words[1]);
949         break;
950
951       case cEndPackage :
952                           commandEndPackage();
953 //EED Borrame        mVirtualExecuter->EndPackage();
954         break;
955
956       case cDefine :
957         if (mFileName.size()>0) 
958         {
959 //???                   commandDefine(????);
960                    filename = mFileName.back(); //mIncludeFileName.back(); //Utilities::get_file_name(mFileName.back());
961         }
962         if (words.size()==2) 
963         {
964                         std::string packTmp = "";
965                         commandDefine(words[1],packTmp,filename);
966 //EED Borrame           mVirtualExecuter->Define(words[1],"",filename);
967         }
968         else
969         {
970                         commandDefine(words[1],words[2],filename);
971 //EED Borrame           mVirtualExecuter->Define(words[1],words[2],filename);
972         }
973         break;
974
975       case cEndDefine :
976                 commandEndDefine();
977 //EED Borrame        mVirtualExecuter->EndDefine();
978         break;
979
980       case cKind :
981                         commandKind(words[1]);
982 //EED Borrame        mVirtualExecuter->Kind(words[1]);
983         break;
984
985       case cPrint :
986                           commandPrint(words[1]);
987 //EED Borrame        mVirtualExecuter->Print(words[1]);
988         break;
989                           
990       case cExec :
991                           commandExec(words[1]);
992 //EED Borrame        if (words[1]=="freeze") 
993 //EED Borrame     {
994 //EED Borrame       mVirtualExecuter->SetNoExecMode(true);
995 //EED Borrame       mThrow = false;
996 //EED Borrame     }
997 //EED Borrame   else if (words[1]=="freeze_no_error") 
998 //EED Borrame     {
999 //EED Borrame       mVirtualExecuter->SetNoExecMode(true);
1000 //EED Borrame       mVirtualExecuter->SetNoErrorMode(true);
1001 //EED Borrame       mThrow = false;
1002 //EED Borrame     }
1003 //EED Borrame   else if (words[1]=="unfreeze") 
1004 //EED Borrame     {
1005 //EED Borrame       mVirtualExecuter->SetNoExecMode(false);
1006 //EED Borrame       mVirtualExecuter->SetNoErrorMode(false);
1007 //EED Borrame     }
1008 //EED Borrame   else
1009 //EED Borrame     {
1010 //EED Borrame       mVirtualExecuter->Execute(words[1]);
1011 //EED Borrame     }
1012                           
1013         break;
1014
1015       case cInput :
1016         Utilities::SplitAroundFirstDot(words[2],left,right);
1017                           commandInput(words[1],left,right,words[3]);
1018 //EED Borrame        mVirtualExecuter->DefineInput(words[1],left,right,words[3]);
1019         break;
1020
1021       case cOutput :
1022         Utilities::SplitAroundFirstDot(words[2],left,right);
1023                 commandOutput(words[1],left,right,words[3]);
1024 //EED Borrame         mVirtualExecuter->DefineOutput(words[1],left,right,words[3]);
1025         break;
1026
1027       case cSet :
1028         Utilities::SplitAroundFirstDot(words[1],left,right);
1029                 commandSet(left,right,words[2]);
1030 //EED Borrame        mVirtualExecuter->Set(left,right,words[2]);
1031         break;
1032
1033       case cAuthor :
1034                 commandAuthor(words[1]);
1035 //EED Borrame        mVirtualExecuter->Author(words[1]);
1036         break;
1037
1038       case cNewGUI :
1039                 commandNewGUI(words[1],words[2]);
1040         break;
1041
1042       case cCategory :
1043                 commandCategory(words[1]);
1044 //EED Borrame   mVirtualExecuter->Category(words[1]);
1045         break;
1046
1047       case cIndex :
1048         if (words.size()==1)
1049                         commandIndex("tmp_index.html");
1050         else if (words.size()==2)
1051                         commandIndex(words[1]);
1052         else if (words.size()==3)
1053                         commandIndex(words[1],words[2]);
1054         break;
1055
1056       case cDescription :
1057                 commandDescription(words[1]);
1058 //EED Borrame        mVirtualExecuter->Description(words[1]);
1059         break;
1060
1061       case cHelp :
1062         commandHelp(words);
1063         break;
1064
1065
1066       case cGraph :
1067         commandGraph(words);
1068         break;
1069
1070       case cConfig :
1071         commandConfig();
1072         break;
1073
1074       case cReset :  
1075         commandReset();
1076         break;
1077         
1078       case cClear :  
1079                 commandClear();
1080 //EED Borrame           mVirtualExecuter->Clear();
1081         break;
1082
1083       case cInclude :
1084                           commandInclude( words[1] , (words.size()==3) );
1085 //EED Borrame           // if 'source' was given (words.size()==3) then tell to set the 
1086 //EED Borrame           // source file name of the current complex box with the full file name included
1087 //EED Borrame           if (mCommandLine)
1088 //EED Borrame        {
1089 //EED Borrame           InterpretFile(words[1],(words.size()==3)); 
1090 //EED Borrame        } else{
1091 //EED Borrame            SwitchToFile(words[1],(words.size()==3) );
1092 //EED Borrame        }
1093                 break;
1094
1095       case cLoad:
1096                 commandLoad( words[1] );
1097 //EED Borrame        GetExecuter()->LoadPackage(words[1]);
1098         break;
1099
1100       case cUnload:
1101                 commandUnload( words[1] );
1102 //EED Borrame        GetExecuter()->UnLoadPackage(words[1]);
1103         break;
1104
1105       case cDebug :
1106                           if (words.size()==2) commandDebug(words[1]);
1107                                 else commandDebug("");
1108         break;
1109                           
1110         /* obsolete
1111       case cWorkspace :
1112         if (words.size() == 2) 
1113         {
1114            if (words[1]=="freeze")        mVirtualExecuter->SetNoExecMode(true);
1115            else if (words[1]=="unfreeze") mVirtualExecuter->SetNoExecMode(false);
1116         }
1117         else
1118         {
1119            mVirtualExecuter->SetWorkspaceName(words[2]);
1120         }
1121         break;
1122         */
1123       default:
1124         bbtkInternalError("should not reach here !!!");
1125    }
1126
1127     bbtkDebugMessage("interpreter",6,"<== InterpreterVirtual::DoInterpretLine(\""
1128                      <<line<<"\")"<<std::endl);
1129
1130   }
1131   //=======================================================================  
1132
1133
1134
1135
1136
1137   //=======================================================================
1138   void InterpreterVirtual::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
1139 {
1140     bbtkDebugMessage("interpreter",9,"==> InterpreterVirtual::SplitLine(\""<<str<<"\")"<<std::endl);
1141
1142     std::string delimiters = "\"";
1143     std::vector<std::string> quote;
1144     Utilities::SplitString(str,delimiters,quote);
1145
1146     delimiters = " \t";
1147     std::vector<std::string>::iterator i;
1148     for (i=quote.begin(); i!=quote.end(); ) 
1149     {
1150        Utilities::SplitString(*i,delimiters,tokens);
1151        ++i;
1152        if (i!=quote.end()) 
1153        {
1154         //    bbtkDebugMessage("interpreter",0,"\""<<*i<<"\""<<std::endl);
1155           tokens.push_back(*i);
1156           ++i;
1157        }
1158     }
1159
1160     for (i=tokens.begin(); i!=tokens.end(); ++i) 
1161     {
1162       bbtkDebugMessage("interpreter",9,"--["<<*i<<"]"<<std::endl);
1163     }
1164     bbtkDebugMessage("interpreter",9,"<== InterpreterVirtual::SplitLine(\""<<str<<"\")"<<std::endl);
1165
1166  }
1167   //=======================================================================
1168
1169
1170   //=======================================================================
1171   void InterpreterVirtual::commandReset()
1172   {
1173   }
1174   //=======================================================================
1175
1176   //=======================================================================
1177   /**
1178    *
1179    */
1180   /*
1181   void InterpreterVirtual::Print( const std::string& str)
1182   {
1183     if (mVirtualExecuter->GetNoExecMode()) return;
1184
1185     bbtkDebugMessageInc("interpreter",9,"InterpreterVirtual::Print(\""<<str<<"\")"<<std::endl);
1186
1187  // TO DO :
1188  // InterpretLine ("load std")
1189  // InterpretLine("new ConcatStrings _C_ ") -> trouver un nom unique : # commande 
1190  // InterpretLine("new Print _P_") 
1191  // InterpretLine("connect _C_.Out _P_.In")
1192  // int num = 1
1193  
1194
1195     std::vector<std::string> chains;
1196     std::string delimiters("$");
1197
1198     // Skip delimiters at beginning.
1199     std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
1200     bool is_text = true;
1201     if (lastPos>0) is_text = false;
1202
1203     // Find first delimiter.
1204     std::string::size_type pos     = str.find_first_of(delimiters, lastPos);
1205
1206     while (std::string::npos != pos || std::string::npos != lastPos)
1207     {
1208        if (is_text) 
1209        {
1210           // Found a text token, add it to the vector.
1211           chains.push_back(str.substr(lastPos, pos - lastPos));
1212  // std::string token = str.substr(lastPos, pos - lastPos)
1213  // InterpretLine("set _C_.In%num% %token%")
1214  
1215        }
1216        else 
1217        {
1218
1219        // is an output (between $$) : decode 
1220          std::string tok,box,output;
1221          tok = str.substr(lastPos, pos - lastPos);
1222          Utilities::SplitAroundFirstDot(tok,box,output);
1223          chains.push_back( mVirtualExecuter->Get(box,output) );
1224
1225 // InterpretLine("connect %tok% _C_.In%num%") 
1226
1227        }
1228         // Skip delimiters.  Note the "not_of"
1229        lastPos = str.find_first_not_of(delimiters, pos);
1230         // Find next delimiter
1231        pos = str.find_first_of(delimiters, lastPos);
1232     //
1233        is_text = !is_text;
1234 // num ++;
1235      }
1236 // InterpretLine("exec _P_")
1237 // if (IS_IN_WORKSPACE) InterpretLine("delete _C_; delete _P_");
1238
1239      std::vector<std::string>::iterator i;
1240      for (i= chains.begin(); i!=chains.end(); ++i) 
1241      {
1242
1243        Utilities::SubsBackslashN(*i);
1244        std::cout << *i;
1245      }
1246      std::cout << std::endl;
1247      bbtkDebugDecTab("interpreter",9);
1248  }
1249 */
1250
1251   //=======================================================================
1252   /**
1253    *
1254    */
1255
1256   // =========================================================================
1257   void InterpreterVirtual::SwitchToFile( const std::string& name , bool source )
1258   {
1259   // Note : in the following :
1260   // name : the user supplied name 
1261   //      - abreviated name    e.g.       scr   scr.bbs
1262   //      - relative full name e.g.       ./scr.bbs   ../../scr.bbs 
1263   //      - absolute full name e.g.       /home/usrname/proj/dir/scr.bbs
1264   //          same for Windows, with      c:, d: ...
1265   //
1266   // use ./directory/subdir/scrname.bbs
1267   //
1268
1269     bbtkDebugMessage("interpreter",4,"==> InterpreterVirtual::SwitchToFile( \""
1270                      <<name<<"\")"<<std::endl);
1271
1272     std::vector<std::string> script_paths;
1273     std::string fullPathScriptName;  // full path script name
1274     std::string pkgname;             // e.g. <scriptname>.bbs
1275     std::vector<std::string> Filenames;
1276           std::string tmpFilenames;
1277           
1278     // The following is *NOT* a debug time message :
1279     // It's a user intended message.
1280     // Please don't remove it.
1281     bbtkMessage("interpreter",1,
1282         "look for : [" << name
1283         << "]" << std::endl);
1284
1285
1286     std::string upath;
1287     pkgname = Utilities::ExtractScriptName(name,upath);
1288
1289     bbtkMessage("interpreter",3,
1290                 "package name:[" << pkgname
1291                  << "] path:[" << upath << "]" << std::endl);
1292     bool fullnameGiven = false; 
1293     bool foundFile     = false;
1294
1295     // ==== "*" provided : load all scripts in given path 
1296     // relative (e.g. std/boxes/*) or absolute 
1297     if (pkgname == "*") 
1298       {
1299
1300         std::stringstream* stream = new std::stringstream;
1301         //if (upath.size()!=0) // avoid troubles for "*"
1302                   
1303         // ==== no path provided : look in root bbs path
1304         if (upath.size()==0)
1305           {
1306             //      bbtkMessage("interpreter",1,
1307             // LG : add all bbs path
1308             //  script_paths.push_back(  ConfigurationFile::GetInstance().Get_root_bbs_path() );
1309             std::vector<std::string>::const_iterator i;
1310             for (i=ConfigurationFile::GetInstance().Get_bbs_paths().begin();
1311                  i!=ConfigurationFile::GetInstance().Get_bbs_paths().end();
1312                  i++)
1313               {
1314                 script_paths.push_back(*i);
1315               }
1316           }
1317         // ==== absolute path provided 
1318         else if (upath[0]=='/' || upath[1] == ':' ) 
1319           {
1320             if ( Utilities::IsDirectory( upath ) )
1321               {
1322                 script_paths.push_back(upath);
1323               }
1324             else 
1325               {
1326                 bbtkError("'"<<upath<<"' : directory does not exist"); 
1327               }
1328           }
1329         // ==== relative path provided : search all bbs path appended with 
1330         // the relative path provided
1331         else
1332           {    
1333             std::vector<std::string>::const_iterator i;
1334             for (i=ConfigurationFile::GetInstance().Get_bbs_paths().begin();
1335                  i!=ConfigurationFile::GetInstance().Get_bbs_paths().end();
1336                  i++)
1337               {
1338                 std::string full_path(*i);
1339                 // we *really* want '.' to be the current working directory
1340                 if (full_path == ".") 
1341                   {
1342                     char buf[2048]; // for getcwd
1343                     char * currentDir = getcwd(buf, 2048);
1344                     std::string cwd(currentDir);
1345                     full_path = currentDir;
1346                   } // if full_path
1347                 
1348                 full_path += ConfigurationFile::GetInstance().Get_file_separator();
1349                 full_path += upath;
1350                 
1351                 if ( Utilities::IsDirectory( full_path ) )
1352                   {
1353                     script_paths.push_back(full_path);
1354                   }
1355               } 
1356             if (script_paths.empty())
1357               {
1358                 bbtkError("no '"<<upath<<"' subdir found in search paths" 
1359                           << std::endl);
1360               }
1361           }
1362         
1363         // === search paths list complete : now explore it
1364         int nbBssFiles = 0;     
1365         // ==== relative name, iterate + load all .bbs/.bbp files
1366         std::vector<std::string>::iterator i;
1367         for (i=script_paths.begin();i!=script_paths.end();i++)
1368           {
1369                   
1370             bbtkMessage("interpreter",1,
1371                         "--> Looking in '" << *i << "'" << std::endl);
1372             
1373             Filenames.clear();
1374             //int nbFiles = 
1375             Utilities::Explore(*i, false, Filenames);
1376
1377                   int iFilesnames,jFilesnames,sizeFilenames;
1378                   sizeFilenames=Filenames.size();
1379                   
1380                   
1381                   // EEDd 30 sept 2012
1382                   //Sorting list of files
1383                   for (iFilesnames=0;iFilesnames<sizeFilenames; iFilesnames++)
1384               {
1385                           for (jFilesnames=iFilesnames;jFilesnames<sizeFilenames; jFilesnames++)
1386                           {
1387                                   if ( Filenames[iFilesnames] > Filenames[jFilesnames] )
1388                                   {
1389                                           tmpFilenames                          = Filenames[iFilesnames];
1390                                           Filenames[iFilesnames]        = Filenames[jFilesnames];
1391                                           Filenames[jFilesnames]        = tmpFilenames;
1392                                   } // if Filesnames
1393                           } // for iFilesnames
1394               } // for iFilesnames
1395                   
1396                   
1397                   
1398             for (std::vector<std::string>::iterator j = Filenames.begin(); 
1399                  j!= Filenames.end(); ++j)
1400               {
1401                 int lgr = (*j).size();
1402                 if (lgr < 5) continue;  
1403                 // ignore non .bbp file
1404                 if ( (*j).substr(lgr-4, 4) != ".bbp") continue; 
1405                 
1406                 (*stream) << "include \"" << *j << "\"\n";
1407                 bbtkMessage("interpreter",2,"  --> Found '" << *j << "'" << std::endl);
1408                 
1409                 nbBssFiles++;
1410               } // for (std::vector...
1411           } // for (i=script_...
1412
1413         // === Result ...
1414         if (nbBssFiles==0)
1415           {
1416             bbtkMessage("interpreter",1,
1417                         "  --> No .bbp found"<< std::endl);
1418           } 
1419         else 
1420           {
1421             bbtkMessage("interpreter",1,
1422                         "  --> "<<nbBssFiles<<" .bbp found"<< std::endl);
1423             SwitchToStream(stream);
1424           }
1425         return;
1426       }  
1427     //=============== end pkgname=="*" ===========
1428     
1429     
1430     // if name starts with a / or a . or contains : user is assumed to have passed a relative/absolute name
1431     // (not only a plain script name)
1432     // we trust him, and try to expland the directory name
1433     // WARNING : starting from current local directory :  ./whatYouWant  (./ mandatory!)
1434
1435     if (name[0]=='/' || name[1] == ':' || name[0]=='.')  // absolute path (linux/windows) or relative path
1436     { 
1437
1438       // ===========================================================check user supplied location
1439       fullnameGiven = true;
1440
1441       fullPathScriptName =  Utilities::ExpandLibName(name, false);
1442
1443       // allow user to always forget ".bbs"
1444       int l = fullPathScriptName.size();
1445
1446       if (l!=0) 
1447           {
1448          if ((fullPathScriptName.substr(l-4, 4) != ".bbs")&&
1449                          (fullPathScriptName.substr(l-4, 4) != ".bbp"))
1450          {
1451                         std::string tfullPathScriptName = fullPathScriptName + ".bbs";
1452                         if ( Utilities::FileExists(tfullPathScriptName) )
1453                         {
1454                                 fullPathScriptName = tfullPathScriptName;
1455                                 foundFile = true;
1456                         }
1457                         else 
1458                         {
1459                                 tfullPathScriptName = fullPathScriptName + ".bbp";
1460                                 if ( Utilities::FileExists(tfullPathScriptName) )
1461                                 {
1462                                         fullPathScriptName = tfullPathScriptName;
1463                                         foundFile = true;
1464                                 }
1465                         }
1466                  }
1467                  else 
1468                  {
1469                         if ( Utilities::FileExists(fullPathScriptName) )
1470                         {
1471                                 foundFile = true;
1472                         }
1473                  }
1474           } // endif l != 0
1475   }
1476   else
1477   // =============================== iterate on the paths
1478   {
1479       script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
1480       std::string path;
1481       std::vector<std::string>::iterator i;
1482       for (i=script_paths.begin();i!=script_paths.end();++i)
1483           {
1484                 path = *i;
1485                 // we *really* want '.' to be the current working directory
1486                 if (path == ".") 
1487                 {
1488                         char buf[2048]; // for getcwd
1489                         char * currentDir = getcwd(buf, 2048);
1490                         std::string cwd(currentDir);
1491                         path = currentDir;
1492                 }
1493           
1494                 std::string tfullPathScriptName = Utilities::MakePkgnameFromPath(path, name, false);
1495                   
1496 //Addition JCP tfullPathScriptName.size()>=4 
1497                 if(tfullPathScriptName.size()>=4){
1498                         if (tfullPathScriptName.substr(tfullPathScriptName.size()-4, 3)==".bb")
1499                         {
1500                           fullPathScriptName = tfullPathScriptName;
1501                                 if ( ! Utilities::FileExists(fullPathScriptName) )
1502                                 {
1503                                         // The following is *NOT* a debug time message :
1504                                         // It's a user intended message.
1505                                         // Please don't remove it.
1506                                         bbtkMessage("interpreter",2,
1507                                   "   [" <<fullPathScriptName <<"] : does not exist" 
1508                                   <<std::endl);
1509                                         continue;  // try next path
1510                                 }
1511                                 bbtkMessage("interpreter",2,
1512                                           "   [" <<fullPathScriptName 
1513                                           <<"] : found" <<std::endl);
1514                                 foundFile = true;
1515                                 break; // a script was found; we stop iterating
1516                         }
1517                         else 
1518                         {
1519                                 fullPathScriptName = tfullPathScriptName + ".bbs";
1520                                 // Check if library exists
1521                                 if ( ! Utilities::FileExists(fullPathScriptName) )
1522                                 {
1523                                         fullPathScriptName = tfullPathScriptName + ".bbp";
1524                                         if ( ! Utilities::FileExists(fullPathScriptName) )
1525                                         {
1526                                                 // The following is *NOT* a debug time message :
1527                                                 // It's a user intended message.
1528                                                 // Please don't remove it.
1529                                                 bbtkMessage("interpreter",2,
1530                                                 "   [" <<tfullPathScriptName <<".bbs/.bbp] : do not exist" 
1531                                                 <<std::endl);
1532                                                 continue;  // try next path
1533                                         }
1534                                 }
1535                                 bbtkMessage("interpreter",2,
1536                                   "   [" <<fullPathScriptName 
1537                                   <<"] : found" <<std::endl);
1538                                 foundFile = true;
1539                                 break; // a script was found; we stop iterating
1540                         }
1541                 }               
1542         } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
1543   }
1544
1545     if (!foundFile)
1546       {
1547         if (fullnameGiven)
1548           if(fullPathScriptName == "")
1549             bbtkError("Path ["<<upath<<"] doesn't exist");
1550           else
1551             bbtkError("Script ["<<fullPathScriptName<<"] not found");
1552         else
1553           bbtkError("No ["<<pkgname<<".bbs/.bbp] script found");
1554         return;
1555       } else {
1556                 LoadScript(fullPathScriptName,name);
1557                   if (source) 
1558                   {
1559                           // Over writing the fullpath of the bbp file.
1560                           SetCurrentFileName( fullPathScriptName );
1561                           SetTypeOfScript_Application();
1562                   }
1563         }    
1564                   
1565     return;
1566   }
1567   //=======================================================================
1568
1569         //=======================================================================
1570         void InterpreterVirtual::SetCurrentFileName(const std::string &fullPathScriptName)  // virtual 
1571         {
1572         }       
1573         //=======================================================================
1574         
1575         
1576         //=======================================================================
1577         void InterpreterVirtual::SetTypeOfScript_Application( )
1578         {
1579         }
1580         //=======================================================================
1581
1582         
1583   //=======================================================================
1584 void InterpreterVirtual::SwitchToStream( std::stringstream* stream )
1585 {
1586   bbtkDebugMessage("interpreter",4,"==> InterpreterVirtual::SwitchToStream()"
1587                    <<std::endl);
1588    mFile.push_back(stream);
1589     std::ostringstream buffer_name;
1590     bufferNb++;
1591     buffer_name << "buffer_" ;
1592
1593     if (mFileName.size()>0 )
1594     {
1595        buffer_name << mFileName.back() << "_" << mLine.back();
1596     }
1597     mFileName.push_back(buffer_name.str());
1598     mIncludeFileName.push_back(buffer_name.str());
1599     mLine.push_back(0);
1600 }
1601   //=======================================================================
1602
1603   //=======================================================================
1604
1605   void InterpreterVirtual::LoadScript( std::string fullPathScriptName,
1606                                 std::string includeScriptName)
1607   {
1608     bbtkDebugMessage("interpreter",4,"==> InterpreterVirtual::LoadScript("
1609                      <<fullPathScriptName<<")"
1610                      <<std::endl);
1611
1612     Utilities::replace( fullPathScriptName , 
1613                          INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
1614    
1615      if (find(mFileNameHistory.begin(),
1616               mFileNameHistory.end(),
1617               fullPathScriptName)!=mFileNameHistory.end())
1618      {
1619         return;
1620      }
1621
1622     std::ifstream* s;
1623     s = new std::ifstream;
1624     s->open(fullPathScriptName.c_str());
1625     if (!s->good())
1626     {
1627         bbtkError("Could not open file ["<<fullPathScriptName<<"]");
1628         return;
1629     }
1630
1631     bbtkMessage("interpreter",1,"   -->[" << fullPathScriptName 
1632                 << "] found" << std::endl);
1633
1634     mFile.push_back(s);
1635     mFileName.push_back(fullPathScriptName);
1636     mFileNameHistory.push_back(fullPathScriptName);
1637     mIncludeFileName.push_back(includeScriptName);
1638     mLine.push_back(0);
1639
1640     return;
1641   }
1642   //=======================================================================
1643
1644   //=======================================================================
1645   void InterpreterVirtual::CloseCurrentFile()
1646   {
1647     bbtkDebugMessage("interpreter",9,"==> InterpreterVirtual::CloseCurrentFile()"
1648                       <<std::endl);
1649
1650     if (mFile.size()==0)
1651     {
1652       bbtkDebugMessage("interpreter",9," -> no file left open"<<std::endl);
1653       return;
1654     }
1655
1656     bbtkDebugMessage("interpreter",9," Closing file '"<<mFileName.back()<<"'"<<std::endl);
1657
1658     std::ifstream* file = dynamic_cast<std::ifstream*>(mFile.back());
1659     if (file!=0) file->close();
1660
1661     delete mFile.back();
1662     mFile.pop_back();
1663     mFileName.pop_back();
1664     mIncludeFileName.pop_back();
1665     mLine.pop_back();
1666
1667     bbtkDebugMessage("interpreter",9," Remains "
1668                      <<mFile.size()
1669                      <<" open"<<std::endl);
1670     bbtkDebugMessage("interpreter",9,"<== InterpreterVirtual::CloseCurrentFile()"
1671                      <<std::endl);
1672   }
1673   //=======================================================================
1674
1675  //=======================================================================
1676   void InterpreterVirtual::CloseAllFiles()
1677   {
1678     bbtkDebugMessage("interpreter",9,"==> InterpreterVirtual::CloseAllFiles()"
1679                       <<std::endl);
1680
1681     while (mFile.size() != 0) 
1682     {
1683        CloseCurrentFile();
1684     }
1685     bbtkDebugMessage("interpreter",9,"<== InterpreterVirtual::CloseAllFiles()"
1686                       <<std::endl);
1687   }
1688   //=======================================================================
1689
1690
1691
1692   //=======================================================================
1693   void InterpreterVirtual::InterpretCommand( const std::vector<std::string>& words,
1694                                       CommandInfoType& info )
1695   {
1696           
1697     bbtkDebugMessage("interpreter",9,"==> InterpreterVirtual::InterpretCommand(...)"<<std::endl);
1698
1699     // searches the command keyword
1700     CommandDictType::iterator c;
1701     c = mCommandDict.find(words[0]);
1702     if ( c == mCommandDict.end() ) {
1703       bbtkError(words[0]<<" : unknown command");
1704     }
1705
1706     // tests the number of args 
1707     if ( ( ((int)words.size())-1 < c->second.argmin ) ||
1708          ( ((int)words.size())-1 > c->second.argmax ) )
1709     {
1710                 
1711 //EED       HelpCommand(words[0]);
1712                 commandHelp(words[0]);
1713        bbtkError(words[0]<<" : wrong number of arguments");
1714     }
1715 //std::cout<<"InterpreterVirtual::InterpretCommand( const std::vector<std::string>& words,"<<std::endl;
1716     info = c->second;
1717     bbtkDebugMessage("interpreter",9,"<== InterpreterVirtual::InterpretCommand(...)"<<std::endl);
1718
1719   }
1720   //=======================================================================
1721
1722
1723   //=======================================================================
1724   /// Displays help on all the commands
1725   void InterpreterVirtual::commandHelp(const std::vector<std::string>& words) 
1726   { 
1727   }
1728   //=======================================================================
1729   void InterpreterVirtual::commandHelp(const std::string &words) 
1730   {  
1731   }
1732         //=======================================================================
1733         
1734    //===================================================================    
1735   /// Displays the Configuration
1736   void InterpreterVirtual::commandConfig() const
1737   {
1738   }  
1739    //===================================================================    
1740
1741
1742
1743   //=======================================================================
1744   /// Fills the vector commands with the commands which 
1745   /// have the first n chars of buf for prefix
1746   /// TODO : skip initial spaces in buf and also return the position of first
1747   /// non blank char in buf
1748   void InterpreterVirtual::FindCommandsWithPrefix( char* buf,
1749                                             int n,
1750                                             std::vector<std::string>& commands )
1751   {
1752     CommandDictType::const_iterator i;
1753     for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1754     {
1755       if ((i->first).find(buf,0,n) == 0) 
1756         commands.push_back(i->first);
1757     }
1758   }
1759   //=======================================================================
1760
1761
1762
1763   //=======================================================================
1764 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1765   
1766   inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1767   inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1768   
1769   // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1770   // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1771   // E.G. STORE THIS IN bbtk_config.xml
1772 #define BBTK_UP_ARROW_KBCODE    0x00415B1B
1773 #define BBTK_DOWN_ARROW_KBCODE  0x00425B1B
1774 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1775 #define BBTK_LEFT_ARROW_KBCODE  0x00445B1B
1776 #define BBTK_BACKSPACE_KBCODE   0x00000008
1777 #define BBTK_DEL_KBCODE         0x0000007F
1778 #define BBTK_SPACE_KBCODE       0x00000020 
1779
1780   //=======================================================================
1781   void InterpreterVirtual::GetLineFromPrompt(std::string& s)
1782   {
1783     int c;
1784     unsigned int ind=0;
1785
1786     unsigned int MAX_LINE_SIZE = 160;
1787     unsigned int MAX_HISTORY_SIZE = 100;
1788
1789     char* newline = new char[MAX_LINE_SIZE];
1790     memset(newline,0,MAX_LINE_SIZE);
1791     char* histline = new char[MAX_LINE_SIZE];
1792     memset(histline,0,MAX_LINE_SIZE);
1793
1794     char* line = newline;
1795     unsigned int hist = mHistory.size();
1796
1797     write(1,"> ",2);
1798     while(1)
1799     {
1800        c=0;
1801        read ( STDIN_FILENO, &c, 4) ;
1802
1803        bbtkDebugMessage("debug",9,"[0x"<<std::hex<<c<<"]\n");
1804
1805        // Printable character
1806        if ( (ind<MAX_LINE_SIZE-1) &&
1807             ( c >= BBTK_SPACE_KBCODE ) && 
1808             ( c <  BBTK_DEL_KBCODE )) 
1809        {
1810           PrintChar(c);
1811           line[ind++]=c;
1812        }
1813       // CR
1814        else if (c=='\n')
1815        {
1816        // delete the unused line
1817           if (line==newline)
1818               delete histline;
1819           else
1820               delete newline;
1821    
1822     // empty lines are not stored in from history
1823           if (strlen(line)) 
1824           {
1825              // if history too long : delete oldest command
1826              if (mHistory.size()>MAX_HISTORY_SIZE) 
1827              {
1828                 delete mHistory.front();
1829                 mHistory.pop_front();
1830              }
1831              mHistory.push_back(line);
1832           }
1833           break;
1834         }
1835        // Backspace
1836         else if ( (ind>0) && 
1837                   ((c == BBTK_BACKSPACE_KBCODE) ||
1838                    (c == BBTK_DEL_KBCODE)) )
1839           {
1840             line[ind--]=' ';
1841             BackSpace();
1842           }
1843         // Tab 
1844         else if (c=='\t')
1845           {
1846             // TODO : Command completion  
1847             std::vector<std::string> commands;
1848             FindCommandsWithPrefix( line,ind,commands);
1849             if (commands.size()==1) 
1850               {
1851                 std::string com = *commands.begin();
1852                 for (; ind<com.size(); ++ind) 
1853                   {
1854                     PrintChar(com[ind]); 
1855                     line[ind]=com[ind];
1856                   }
1857                 PrintChar(' '); 
1858                 line[ind++]=' ';
1859               }
1860             else if (commands.size()>1) 
1861               {
1862                 std::vector<std::string>::iterator i;
1863                 write(1,"\n",1);
1864                 for (i=commands.begin();i!=commands.end();++i) 
1865                   {
1866                     write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1867                     PrintChar(' ');
1868                   }
1869                 write(STDOUT_FILENO,"\n> ",3);
1870                 //for (int j=0;j<ind;++j) 
1871                   //{
1872                     write(STDOUT_FILENO,line,ind); 
1873                     //  }
1874               }
1875           }
1876         // Arrow up : back in history
1877         else if (c==BBTK_UP_ARROW_KBCODE)
1878           {
1879             if (hist) 
1880               {
1881                 // erase current line
1882                 while (ind--) BackSpace();
1883                 // 
1884                 hist--;
1885                 // 
1886                 strcpy(histline,mHistory[hist]);
1887                 line = histline;
1888                 ind = strlen(line);
1889                 
1890                 write(STDOUT_FILENO,line,ind);
1891               }
1892           }
1893         // Arrow down : down in history
1894         else if (c==BBTK_DOWN_ARROW_KBCODE)
1895           {
1896             if (hist<mHistory.size()-1) 
1897               {
1898                 // erase current line
1899                 while (ind--) BackSpace();
1900                 // 
1901                 hist++;
1902                 // 
1903                 strcpy(histline,mHistory[hist]);
1904                 line = histline;
1905                 ind = strlen(line);
1906                 
1907                 write(STDOUT_FILENO,line,ind);
1908               }
1909             // end of history : switch back to newline
1910             else if (hist==mHistory.size()-1)
1911               {
1912                 // erase current line
1913                 while (ind--) BackSpace();
1914                 // 
1915                 hist++;
1916                 // 
1917                 line = newline;
1918                 ind = strlen(line);
1919                 
1920                 write(STDOUT_FILENO,line,ind);
1921               }
1922           }
1923         // Arrow right
1924         else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1925           {
1926             PrintChar(line[ind]);
1927             ind++;
1928           }
1929
1930         // Arrow left
1931         else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1932           {
1933             PrintChar('\b');
1934             ind--;
1935     
1936           }
1937
1938       }
1939     write(STDOUT_FILENO,"\n\r",2);
1940     
1941     
1942     s = line;
1943     
1944   }
1945 #else
1946
1947   //=======================================================================
1948   void InterpreterVirtual::GetLineFromPrompt(std::string& s)
1949   {  
1950     s.clear();
1951
1952     putchar('>');
1953     putchar(' ');
1954
1955     do 
1956     {
1957       char c = getchar();
1958       if (c=='\n') 
1959       {
1960         putchar('\n');
1961         break;
1962       }
1963       if (c=='\t') 
1964       {
1965         // putchar('T');
1966         continue;
1967       }
1968       // putchar(c);
1969       s += c;
1970     } 
1971     while (true);  
1972     
1973   }
1974   //=======================================================================  
1975
1976 #endif
1977
1978
1979
1980   //=======================================================================
1981   void InterpreterVirtual::CommandLineInterpreter()
1982   {
1983     bbtkDebugMessageInc("interpreter",9,
1984                         "InterpreterVirtual::CommandLineInterpreter()"<<std::endl);
1985
1986 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT  
1987     // Initialise the tty in non canonical mode with no echo
1988     // oter remembers the previous settings to restore them after 
1989     struct termios ter,oter;
1990     tcgetattr(0,&ter);
1991     oter=ter;
1992     ter.c_lflag &= ~ECHO;
1993     ter.c_lflag &= ~ICANON;
1994     ter.c_cc[VMIN]=1;
1995     ter.c_cc[VTIME]=0;
1996     tcsetattr(0,TCSANOW,&ter);
1997 #endif
1998
1999     mCommandLine = true;
2000     bool again = true;
2001     // bool insideComment = false; // for multiline comment  
2002     mInsideComment = false;
2003     do 
2004     {
2005       try
2006       {
2007         std::string line;
2008         GetLineFromPrompt(line);
2009         DoInterpretLine(line); //, insideComment);
2010       }
2011       /*
2012       catch (QuitException e)
2013       {
2014         bbtkMessage("interpreter",1,"Interpreter : Quit"<<std::endl);
2015         again = false;
2016       }
2017       */
2018       catch (bbtk::Exception e) 
2019       {
2020         e.Print();
2021       }
2022         catch (std::exception& e) 
2023       {
2024         std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
2025       }
2026       catch (...)
2027       {
2028         std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
2029       }
2030     }
2031     while (again);
2032
2033 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
2034     tcsetattr(0,TCSANOW,&oter);
2035 #endif
2036
2037     std::cout << "Good bye !" << std::endl;
2038
2039     bbtkDebugDecTab("interpreter",9);
2040   }
2041
2042 //=======================================================================
2043 void InterpreterVirtual::commandGraph(const std::vector<std::string>& words)
2044 {
2045 }
2046 //=======================================================================
2047
2048
2049 //=======================================================================
2050 void  InterpreterVirtual::commandIndex(const std::string& filename, const std::string& type)
2051 {
2052 }
2053 //=======================================================================
2054
2055
2056 //=======================================================================
2057 void  InterpreterVirtual::commandNewGUI(const std::string& boxname,const std::string& instanceName)
2058 {
2059 }
2060 //=======================================================================
2061
2062
2063
2064  //==========================================================================
2065   void InterpreterVirtual::commandDebug(const std::string& name)
2066   {
2067   }
2068  //==========================================================================
2069
2070   /*
2071   //==========================================================================
2072   // Adds a callback when 'break' command issued
2073   void InterpreterVirtual::AddBreakObserver( BreakCallbackType c )
2074   {
2075     mBreakSignal.connect(c);
2076   }
2077  //==========================================================================
2078  */
2079
2080  //==========================================================================
2081   std::string InterpreterVirtual::GetObjectName() const
2082   {
2083     return std::string("InterpreterVirtual");
2084   }
2085   //==========================================================================
2086   
2087   //==========================================================================
2088   std::string  InterpreterVirtual::GetObjectInfo() const 
2089   {
2090     std::stringstream i;
2091     return i.str();
2092   }
2093   //==========================================================================
2094
2095   //==========================================================================
2096 size_t  InterpreterVirtual::GetObjectSize() const 
2097 {
2098   size_t s = Superclass::GetObjectSize();
2099   s += InterpreterVirtual::GetObjectInternalSize();
2100   return s;
2101   }
2102   //==========================================================================
2103   //==========================================================================
2104 size_t  InterpreterVirtual::GetObjectInternalSize() const 
2105 {
2106   size_t s = sizeof(InterpreterVirtual);
2107   return s;
2108   }
2109   //==========================================================================
2110   //==========================================================================
2111   size_t  InterpreterVirtual::GetObjectRecursiveSize() const 
2112   {
2113     size_t s = Superclass::GetObjectRecursiveSize();
2114     s += InterpreterVirtual::GetObjectInternalSize();
2115     return s;
2116   }
2117   //==========================================================================
2118 }//namespace
2119
2120