]> Creatis software - bbtk.git/blob - kernel/src/bbtkInterpreterVirtual.cxx
#3127 BBTK Feature New Normal - branch changeWx28to30 compilation with wxWidgets3
[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 printf("EED InterpreterVirtual::CatchUnknownException Start\n");
520 //EED Borrame   if (GetExecuter()->GetNoErrorMode()) 
521 //EED Borrame       {
522 //EED Borrame   std::string file("?");
523 //EED Borrame   int line = 0;
524 //EED Borrame   if (mFileName.size()) {
525 //EED Borrame     file = mFileName.back();
526 //EED Borrame     line = mLine.back();
527 //EED Borrame   }
528 //EED Borrame           bbtkWarning("UNDEFINED ERROR "
529 //EED Borrame                       <<"("<<file<<":"<<line<<") skipped");
530 //EED Borrame           return;
531 //EED Borrame         }
532     mStatus = Interpreter_ERROR;               
533     if (mThrow) 
534       {
535         bool in_script = false;
536         std::string file("");
537         int line = 0;
538         if (mFileName.size()) {
539           std::ifstream* fs = dynamic_cast<std::ifstream*>(mFile.back());
540           if (fs!=0) in_script = true;    
541           file = mFileName.back();
542           line = mLine.back();
543         }    
544         CloseAllFiles();
545         throw InterpreterException("Unknown exception caught",
546                                    in_script,file,line);
547       }
548     else
549       {
550         std::stringstream mess;
551         mess << "* UNDEFINED ERROR (not a bbtk nor a std exception)" 
552              << std::endl;
553         if (mFileName.size()) {
554           mess << "* FILE  : \""<<mFileName.back()<<"\""<<std::endl;
555           mess << "* LINE  : "<<mLine.back()<<std::endl;
556         }    
557         CloseAllFiles();
558         std::cerr << mess.str();
559       }
560 printf("EED InterpreterVirtual::CatchUnknownException End\n");
561   }
562   //=======================================================================
563
564   //=======================================================================
565   
566 #define CATCH_MACRO                                             \
567   catch (InterpreterException e)                \
568     {                                                                   \
569       CatchInterpreterException(e);             \
570     }                                                                   \
571   catch (bbtk::Exception e)                             \
572     {                                                                   \
573       CatchBbtkException(e);                    \
574     }                                                                   \
575   catch (std::exception& e)                             \
576     {                                                                   \
577       CatchStdException(e);                             \
578     }                                                                   \
579   catch (...)                                                   \
580     {                                                                   \
581       CatchUnknownException();                  \
582     }                                           
583   //=======================================================================
584    
585
586   //=======================================================================
587   InterpreterVirtual::ExitStatus InterpreterVirtual::InterpretFile( const std::string& filename, bool source )
588   {
589           bbtkDebugMessage("interpreter",4,"==> InterpreterVirtual::InterpretFile(\""<<filename<<"\")"<<std::endl);
590
591     bool exm = mCommandLine;
592     mCommandLine = false;
593
594     try 
595     {
596       mStatus = Interpreter_OK;
597       SwitchToFile(filename,source);
598       mInsideComment = false;
599       InterpretCurrentStreams();
600     } 
601     CATCH_MACRO;
602     
603     bbtkDebugMessage("interpreter",4,
604                      "<== InterpreterVirtual::InterpretFile(\""
605                      <<filename<<"\")"<<std::endl);
606
607
608     mCommandLine = exm;
609
610     return mStatus;
611   }
612   //=======================================================================
613
614
615   //=======================================================================
616   InterpreterVirtual::ExitStatus   InterpreterVirtual::InterpretBuffer( std::stringstream* buffer )
617   {
618     bbtkDebugMessage("interpreter",4,"==> InterpreterVirtual::InterpretBuffer()"<<std::endl);
619
620     bool exm = mCommandLine;
621     mCommandLine = false;
622
623     try 
624     {
625       mStatus = Interpreter_OK;
626       SwitchToStream(buffer);
627       mInsideComment = false;
628       InterpretCurrentStreams();
629     }
630     CATCH_MACRO;
631     
632     //    CloseAllFiles();
633     bbtkDebugMessage("interpreter",4,"<== InterpreterVirtual::InterpretBuffer()"<<std::endl);
634
635     
636     mCommandLine = exm;
637
638     return mStatus;
639   }
640   //=======================================================================
641
642   //=======================================================================
643   /// Interprets the currently open streams
644   InterpreterVirtual::ExitStatus InterpreterVirtual::InterpretCurrentStreams()
645   {
646     bbtkDebugMessage("interpreter",4,
647                      "==> InterpreterVirtual::InterpretCurrentStreams()"<<std::endl);
648
649     while (mFile.size()>0) 
650       {
651         while (!mFile.back()->eof()) {
652           mLine.back()++;
653           char buf[500];
654           mFile.back()->getline(buf,500);
655           std::string str(buf);
656           //size 0 JCP 21-09-2009
657           int size=str.length();
658           if(size != 0){
659                   if ( str[ size-1 ]==13  )
660             {
661               str.erase(size-1,1);
662             }
663                   try
664                         {
665                           DoInterpretLine(str);
666                         }
667                   CATCH_MACRO;
668           }
669           
670         } 
671         CloseCurrentFile();
672       }
673     bbtkDebugMessage("interpreter",4,
674                      "<== InterpreterVirtual::InterpretCurrentStreams()"<<std::endl);
675
676     return mStatus;
677   }
678   //=======================================================================
679
680   //=======================================================================
681   /// Runs the interpretation of a command
682   InterpreterVirtual::ExitStatus InterpreterVirtual::InterpretLine( const std::string& line )
683   {
684     bbtkDebugMessage("interpreter",5,"==> InterpreterVirtual::InterpretLine('"<<line<<"')"<<std::endl);
685
686     try 
687     {
688       mStatus = Interpreter_OK;
689       mInsideComment = false;
690 //std::cout<<"JCP bbtkInterpreter.cxx InterpreterVirtual::InterpretLine("<<std::endl;
691       DoInterpretLine(line );
692     }
693     CATCH_MACRO;
694     
695     
696    bbtkDebugMessage("interpreter",5,"<== InterpreterVirtual::InterpretLine('"<<line<<"')"<<std::endl);
697     
698     return mStatus;
699   }
700   //=======================================================================  
701   
702         void InterpreterVirtual::commandNew(const std::string &boxType, const std::string &boxName) // virtual 
703     {
704     }
705         
706         void InterpreterVirtual::commandDelete(const std::string &boxName)
707     {
708     }
709
710         void InterpreterVirtual::commandConnection(const std::string &nodeFrom,const std::string &outputLabel,const std::string &nodeTo,const std::string &inputLabel)
711     {
712     }
713                 
714         void InterpreterVirtual::commandPackage(const std::string &packageName)
715     {
716     }
717         
718         void InterpreterVirtual::commandEndPackage()
719     {
720     }
721         
722         void InterpreterVirtual::commandDefine(const std::string &name,const std::string &pack,const std::string &scriptfilename)
723     {
724     }
725
726         void InterpreterVirtual::commandEndDefine()
727     {
728     }
729
730         void InterpreterVirtual::commandKind(const std::string &kind)
731     {
732     }
733         
734         void InterpreterVirtual::commandPrint(const std::string &value)
735     {
736     }
737         
738         
739         void InterpreterVirtual::commandExec(const std::string &word)
740     {
741     }
742         
743         
744         void InterpreterVirtual::commandInput(const std::string &name,const std::string &box,const std::string &input,const std::string  &help)
745     {
746     }
747         
748         void InterpreterVirtual::commandOutput(const std::string &name,const std::string &box,const std::string &output,const std::string  &help)
749     {
750     }
751         
752         void InterpreterVirtual::commandSet(const std::string &box,const std::string &input,const std::string &value)
753     {
754     }
755
756         void InterpreterVirtual::commandAuthor(const std::string &author)
757     {
758     }
759
760         void InterpreterVirtual::commandCategory(const std::string &categorytype)
761     {
762     }
763         
764         
765         
766         void InterpreterVirtual::commandDescription(const std::string &description)
767     {
768     }
769
770         
771         void InterpreterVirtual::commandClear()
772     {
773     }
774         
775         void InterpreterVirtual::commandInclude(const std::string &word, bool ok)
776     {
777     }
778         
779         
780         void InterpreterVirtual::commandLoad(const std::string &packageName)
781     {
782     }
783
784         void InterpreterVirtual::commandUnload(const std::string &packageName)
785     {
786     }
787         
788         void InterpreterVirtual::commandBreak()
789     {
790     }
791         
792         void InterpreterVirtual::commandQuit()
793     {
794     }
795         
796         void InterpreterVirtual::commandMessage()
797     {
798     }
799         
800         void InterpreterVirtual::commandMessage(const std::string &kind,const std::string &levelstr)
801     {
802     }
803         
804         
805         
806   //=======================================================================  
807   void InterpreterVirtual::DoInterpretLine( const std::string& line )
808   {  
809     bbtkDebugMessage("interpreter",6,"==> InterpreterVirtual::DoInterpretLine(\""
810                      <<line<<"\")"<<std::endl);
811     std::vector<std::string> words;
812     SplitLine(line,words);
813
814           
815           
816     // Empty line
817     if (words.size()<1) 
818     {
819        bbtkDebugDecTab("interpreter",9);
820        return;
821     }
822
823     // Single line comment : # or //
824     if ( words[0][0]=='#' || (words[0][0]=='/' && words[0][1]=='/') ) 
825     {  
826        bbtkDebugDecTab("interpreter",9);
827        bbtkMessage("interpreter",9,"Comment"<<std::endl);
828        return;
829     }
830
831     // Multi line comment ( /* ... */ ) -delimiters on different lines !-
832     
833     if (words[0][0]=='/' && words[0][1]=='*') 
834     {  
835        bbtkDebugDecTab("interpreter",9);
836        bbtkMessage("interpreter",9,"In multiline comment"<<std::endl);
837        mInsideComment = true;
838        return;
839     }
840
841     if (words[0][0]=='*' && words[0][1]=='/') 
842     {  
843        bbtkDebugDecTab("interpreter",9);
844        bbtkMessage("interpreter",9,"Out multiline comment"<<std::endl);
845        if ( !mInsideComment ) {
846           bbtkDebugDecTab("interpreter",9);
847           bbtkMessage("interpreter",9,"Comment mismatch : '*/' with no matching '/*'"<<std::endl);       
848        }
849        mInsideComment = false;
850        return;
851     }
852
853     if (mInsideComment) 
854     {  
855        bbtkDebugDecTab("interpreter",9);
856        bbtkMessage("interpreter",9,"Multiline Comment"<<std::endl);
857        return;
858     }
859           
860
861     // Command 
862     CommandInfoType command;
863     InterpretCommand(words,command);
864 //std::cout<<"JCP bbtkInterpreter command.keyword ="<<command.keyword<<std::endl;
865     bbtkDebugMessage("interpreter",9,
866                      "Command='"<<command.keyword
867                       <<"' code="<<command.code<<std::endl); 
868           
869     std::string left,right,left2,right2;
870     std::string filename;
871
872     // message command
873     if (command.code==cMessage)
874       {
875         if (words.size()<3)
876           {
877                   commandMessage();
878 //EED Borrame       mVirtualExecuter->HelpMessages();
879           }
880         else
881           {
882                 commandMessage(words[1],words[2]);
883 //EED Borrame           sscanf(words[2].c_str(),"%d",&level);
884 //EED Borrame       mVirtualExecuter->SetMessageLevel(words[1],level);
885           }
886         return;
887       }
888     else 
889       {
890         bbtkMessage("echo",2,line<<std::endl);
891       }
892
893     // break and quit commands
894     if ((command.code==cBreak) || (command.code==cQuit))
895     {
896 //EED-Borrame   bool in_script = false;
897 //EED-Borrame   std::string file("");
898 //EED-Borrame   int line = 0;
899
900 //EED-Borrame   if (mFileName.size()) 
901 //EED-Borrame     {
902 //EED-Borrame       std::ifstream* fs = dynamic_cast<std::ifstream*>(mFile.back());
903 //EED-Borrame       if (fs!=0) in_script = true;          
904 //EED-Borrame       file = mFileName.back();
905 //EED-Borrame       line = mLine.back();
906 //EED-Borrame     } 
907           if (command.code==cBreak)
908           {
909             /*
910             std::cout << "BreakException(" 
911                       <<in_script<<","
912                       <<file<<","
913                       <<line<<")"<<std::endl;
914             */
915                   commandBreak();
916 //EED Borrame       bbtkError("break");//,in_script,file,line);
917             //      throw BreakException(in_script,file,line);
918           } else {
919                   commandQuit();
920 //EED Borrame       bbtkError("quit");//,in_script,file,line);
921               //throw QuitException(in_script,file,line);
922           } // cBreak
923           return;
924    } // cBreak  cQuit  
925 //std::cout<<" mVirtualExecuter->Create(words[1],words[2]); "<<line<<std::endl;
926     // other cammands
927
928           
929     switch (command.code) 
930       {
931       case cNew :
932                 commandNew(words[1],words[2]);
933 //EED Borrame        mVirtualExecuter->Create(words[1],words[2]);
934         break;
935
936       case cDelete :
937                           commandDelete(words[1]);
938 //EED Borrame   mVirtualExecuter->Destroy(words[1]);
939         break;
940
941       case cConnect :
942         Utilities::SplitAroundFirstDot(words[1],left,right);
943         Utilities::SplitAroundFirstDot(words[2],left2,right2);      
944         commandConnection(left,right,left2,right2);
945 //EED Borrame        mVirtualExecuter->Connect(left,right,left2,right2);
946         break;
947
948       case cPackage :
949                           commandPackage(words[1]);
950 //EED Borrame                mVirtualExecuter->BeginPackage(words[1]);
951         break;
952
953       case cEndPackage :
954                           commandEndPackage();
955 //EED Borrame        mVirtualExecuter->EndPackage();
956         break;
957
958       case cDefine :
959         if (mFileName.size()>0) 
960         {
961 //???                   commandDefine(????);
962                    filename = mFileName.back(); //mIncludeFileName.back(); //Utilities::get_file_name(mFileName.back());
963         }
964         if (words.size()==2) 
965         {
966                         std::string packTmp = "";
967                         commandDefine(words[1],packTmp,filename);
968 //EED Borrame           mVirtualExecuter->Define(words[1],"",filename);
969         }
970         else
971         {
972                         commandDefine(words[1],words[2],filename);
973 //EED Borrame           mVirtualExecuter->Define(words[1],words[2],filename);
974         }
975         break;
976
977       case cEndDefine :
978                 commandEndDefine();
979 //EED Borrame        mVirtualExecuter->EndDefine();
980         break;
981
982       case cKind :
983                         commandKind(words[1]);
984 //EED Borrame        mVirtualExecuter->Kind(words[1]);
985         break;
986
987       case cPrint :
988                           commandPrint(words[1]);
989 //EED Borrame        mVirtualExecuter->Print(words[1]);
990         break;
991                           
992       case cExec :
993                           commandExec(words[1]);
994 //EED Borrame        if (words[1]=="freeze") 
995 //EED Borrame     {
996 //EED Borrame       mVirtualExecuter->SetNoExecMode(true);
997 //EED Borrame       mThrow = false;
998 //EED Borrame     }
999 //EED Borrame   else if (words[1]=="freeze_no_error") 
1000 //EED Borrame     {
1001 //EED Borrame       mVirtualExecuter->SetNoExecMode(true);
1002 //EED Borrame       mVirtualExecuter->SetNoErrorMode(true);
1003 //EED Borrame       mThrow = false;
1004 //EED Borrame     }
1005 //EED Borrame   else if (words[1]=="unfreeze") 
1006 //EED Borrame     {
1007 //EED Borrame       mVirtualExecuter->SetNoExecMode(false);
1008 //EED Borrame       mVirtualExecuter->SetNoErrorMode(false);
1009 //EED Borrame     }
1010 //EED Borrame   else
1011 //EED Borrame     {
1012 //EED Borrame       mVirtualExecuter->Execute(words[1]);
1013 //EED Borrame     }
1014                           
1015         break;
1016
1017       case cInput :
1018         Utilities::SplitAroundFirstDot(words[2],left,right);
1019                           commandInput(words[1],left,right,words[3]);
1020 //EED Borrame        mVirtualExecuter->DefineInput(words[1],left,right,words[3]);
1021         break;
1022
1023       case cOutput :
1024         Utilities::SplitAroundFirstDot(words[2],left,right);
1025                 commandOutput(words[1],left,right,words[3]);
1026 //EED Borrame         mVirtualExecuter->DefineOutput(words[1],left,right,words[3]);
1027         break;
1028
1029       case cSet :
1030         Utilities::SplitAroundFirstDot(words[1],left,right);
1031                 commandSet(left,right,words[2]);
1032 //EED Borrame        mVirtualExecuter->Set(left,right,words[2]);
1033         break;
1034
1035       case cAuthor :
1036                 commandAuthor(words[1]);
1037 //EED Borrame        mVirtualExecuter->Author(words[1]);
1038         break;
1039
1040       case cNewGUI :
1041                 commandNewGUI(words[1],words[2]);
1042         break;
1043
1044       case cCategory :
1045                 commandCategory(words[1]);
1046 //EED Borrame   mVirtualExecuter->Category(words[1]);
1047         break;
1048
1049       case cIndex :
1050         if (words.size()==1)
1051                         commandIndex("tmp_index.html");
1052         else if (words.size()==2)
1053                         commandIndex(words[1]);
1054         else if (words.size()==3)
1055                         commandIndex(words[1],words[2]);
1056         break;
1057
1058       case cDescription :
1059                 commandDescription(words[1]);
1060 //EED Borrame        mVirtualExecuter->Description(words[1]);
1061         break;
1062
1063       case cHelp :
1064         commandHelp(words);
1065         break;
1066
1067
1068       case cGraph :
1069         commandGraph(words);
1070         break;
1071
1072       case cConfig :
1073         commandConfig();
1074         break;
1075
1076       case cReset :  
1077         commandReset();
1078         break;
1079         
1080       case cClear :  
1081                 commandClear();
1082 //EED Borrame           mVirtualExecuter->Clear();
1083         break;
1084
1085       case cInclude :
1086                           commandInclude( words[1] , (words.size()==3) );
1087 //EED Borrame           // if 'source' was given (words.size()==3) then tell to set the 
1088 //EED Borrame           // source file name of the current complex box with the full file name included
1089 //EED Borrame           if (mCommandLine)
1090 //EED Borrame        {
1091 //EED Borrame           InterpretFile(words[1],(words.size()==3)); 
1092 //EED Borrame        } else{
1093 //EED Borrame            SwitchToFile(words[1],(words.size()==3) );
1094 //EED Borrame        }
1095                 break;
1096
1097       case cLoad:
1098                 commandLoad( words[1] );
1099 //EED Borrame        GetExecuter()->LoadPackage(words[1]);
1100         break;
1101
1102       case cUnload:
1103                 commandUnload( words[1] );
1104 //EED Borrame        GetExecuter()->UnLoadPackage(words[1]);
1105         break;
1106
1107       case cDebug :
1108                           if (words.size()==2) commandDebug(words[1]);
1109                                 else commandDebug("");
1110         break;
1111                           
1112         /* obsolete
1113       case cWorkspace :
1114         if (words.size() == 2) 
1115         {
1116            if (words[1]=="freeze")        mVirtualExecuter->SetNoExecMode(true);
1117            else if (words[1]=="unfreeze") mVirtualExecuter->SetNoExecMode(false);
1118         }
1119         else
1120         {
1121            mVirtualExecuter->SetWorkspaceName(words[2]);
1122         }
1123         break;
1124         */
1125       default:
1126         bbtkInternalError("should not reach here !!!");
1127    }
1128
1129     bbtkDebugMessage("interpreter",6,"<== InterpreterVirtual::DoInterpretLine(\""
1130                      <<line<<"\")"<<std::endl);
1131
1132   }
1133   //=======================================================================  
1134
1135
1136
1137
1138
1139   //=======================================================================
1140   void InterpreterVirtual::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
1141 {
1142     bbtkDebugMessage("interpreter",9,"==> InterpreterVirtual::SplitLine(\""<<str<<"\")"<<std::endl);
1143
1144     std::string delimiters = "\"";
1145     std::vector<std::string> quote;
1146     Utilities::SplitString(str,delimiters,quote);
1147
1148     delimiters = " \t";
1149     std::vector<std::string>::iterator i;
1150     for (i=quote.begin(); i!=quote.end(); ) 
1151     {
1152        Utilities::SplitString(*i,delimiters,tokens);
1153        ++i;
1154        if (i!=quote.end()) 
1155        {
1156         //    bbtkDebugMessage("interpreter",0,"\""<<*i<<"\""<<std::endl);
1157           tokens.push_back(*i);
1158           ++i;
1159        }
1160     }
1161
1162     for (i=tokens.begin(); i!=tokens.end(); ++i) 
1163     {
1164       bbtkDebugMessage("interpreter",9,"--["<<*i<<"]"<<std::endl);
1165     }
1166     bbtkDebugMessage("interpreter",9,"<== InterpreterVirtual::SplitLine(\""<<str<<"\")"<<std::endl);
1167
1168  }
1169   //=======================================================================
1170
1171
1172   //=======================================================================
1173   void InterpreterVirtual::commandReset()
1174   {
1175   }
1176   //=======================================================================
1177
1178   //=======================================================================
1179   /**
1180    *
1181    */
1182   /*
1183   void InterpreterVirtual::Print( const std::string& str)
1184   {
1185     if (mVirtualExecuter->GetNoExecMode()) return;
1186
1187     bbtkDebugMessageInc("interpreter",9,"InterpreterVirtual::Print(\""<<str<<"\")"<<std::endl);
1188
1189  // TO DO :
1190  // InterpretLine ("load std")
1191  // InterpretLine("new ConcatStrings _C_ ") -> trouver un nom unique : # commande 
1192  // InterpretLine("new Print _P_") 
1193  // InterpretLine("connect _C_.Out _P_.In")
1194  // int num = 1
1195  
1196
1197     std::vector<std::string> chains;
1198     std::string delimiters("$");
1199
1200     // Skip delimiters at beginning.
1201     std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
1202     bool is_text = true;
1203     if (lastPos>0) is_text = false;
1204
1205     // Find first delimiter.
1206     std::string::size_type pos     = str.find_first_of(delimiters, lastPos);
1207
1208     while (std::string::npos != pos || std::string::npos != lastPos)
1209     {
1210        if (is_text) 
1211        {
1212           // Found a text token, add it to the vector.
1213           chains.push_back(str.substr(lastPos, pos - lastPos));
1214  // std::string token = str.substr(lastPos, pos - lastPos)
1215  // InterpretLine("set _C_.In%num% %token%")
1216  
1217        }
1218        else 
1219        {
1220
1221        // is an output (between $$) : decode 
1222          std::string tok,box,output;
1223          tok = str.substr(lastPos, pos - lastPos);
1224          Utilities::SplitAroundFirstDot(tok,box,output);
1225          chains.push_back( mVirtualExecuter->Get(box,output) );
1226
1227 // InterpretLine("connect %tok% _C_.In%num%") 
1228
1229        }
1230         // Skip delimiters.  Note the "not_of"
1231        lastPos = str.find_first_not_of(delimiters, pos);
1232         // Find next delimiter
1233        pos = str.find_first_of(delimiters, lastPos);
1234     //
1235        is_text = !is_text;
1236 // num ++;
1237      }
1238 // InterpretLine("exec _P_")
1239 // if (IS_IN_WORKSPACE) InterpretLine("delete _C_; delete _P_");
1240
1241      std::vector<std::string>::iterator i;
1242      for (i= chains.begin(); i!=chains.end(); ++i) 
1243      {
1244
1245        Utilities::SubsBackslashN(*i);
1246        std::cout << *i;
1247      }
1248      std::cout << std::endl;
1249      bbtkDebugDecTab("interpreter",9);
1250  }
1251 */
1252
1253   //=======================================================================
1254   /**
1255    *
1256    */
1257
1258   // =========================================================================
1259   void InterpreterVirtual::SwitchToFile( const std::string& name , bool source )
1260   {
1261   // Note : in the following :
1262   // name : the user supplied name 
1263   //      - abreviated name    e.g.       scr   scr.bbs
1264   //      - relative full name e.g.       ./scr.bbs   ../../scr.bbs 
1265   //      - absolute full name e.g.       /home/usrname/proj/dir/scr.bbs
1266   //          same for Windows, with      c:, d: ...
1267   //
1268   // use ./directory/subdir/scrname.bbs
1269   //
1270
1271     bbtkDebugMessage("interpreter",4,"==> InterpreterVirtual::SwitchToFile( \""
1272                      <<name<<"\")"<<std::endl);
1273
1274     std::vector<std::string> script_paths;
1275     std::string fullPathScriptName;  // full path script name
1276     std::string pkgname;             // e.g. <scriptname>.bbs
1277     std::vector<std::string> Filenames;
1278           std::string tmpFilenames;
1279           
1280     // The following is *NOT* a debug time message :
1281     // It's a user intended message.
1282     // Please don't remove it.
1283     bbtkMessage("interpreter",1,
1284         "look for : [" << name
1285         << "]" << std::endl);
1286
1287
1288     std::string upath;
1289     pkgname = Utilities::ExtractScriptName(name,upath);
1290
1291     bbtkMessage("interpreter",3,
1292                 "package name:[" << pkgname
1293                  << "] path:[" << upath << "]" << std::endl);
1294     bool fullnameGiven = false; 
1295     bool foundFile     = false;
1296
1297     // ==== "*" provided : load all scripts in given path 
1298     // relative (e.g. std/boxes/*) or absolute 
1299     if (pkgname == "*") 
1300       {
1301
1302         std::stringstream* stream = new std::stringstream;
1303         //if (upath.size()!=0) // avoid troubles for "*"
1304                   
1305         // ==== no path provided : look in root bbs path
1306         if (upath.size()==0)
1307           {
1308             //      bbtkMessage("interpreter",1,
1309             // LG : add all bbs path
1310             //  script_paths.push_back(  ConfigurationFile::GetInstance().Get_root_bbs_path() );
1311             std::vector<std::string>::const_iterator i;
1312             for (i=ConfigurationFile::GetInstance().Get_bbs_paths().begin();
1313                  i!=ConfigurationFile::GetInstance().Get_bbs_paths().end();
1314                  i++)
1315               {
1316                 script_paths.push_back(*i);
1317               }
1318           }
1319         // ==== absolute path provided 
1320         else if (upath[0]=='/' || upath[1] == ':' ) 
1321           {
1322             if ( Utilities::IsDirectory( upath ) )
1323               {
1324                 script_paths.push_back(upath);
1325               }
1326             else 
1327               {
1328                 bbtkError("'"<<upath<<"' : directory does not exist"); 
1329               }
1330           }
1331         // ==== relative path provided : search all bbs path appended with 
1332         // the relative path provided
1333         else
1334           {    
1335             std::vector<std::string>::const_iterator i;
1336             for (i=ConfigurationFile::GetInstance().Get_bbs_paths().begin();
1337                  i!=ConfigurationFile::GetInstance().Get_bbs_paths().end();
1338                  i++)
1339               {
1340                 std::string full_path(*i);
1341                 // we *really* want '.' to be the current working directory
1342                 if (full_path == ".") 
1343                   {
1344                     char buf[2048]; // for getcwd
1345                     char * currentDir = getcwd(buf, 2048);
1346                     std::string cwd(currentDir);
1347                     full_path = currentDir;
1348                   } // if full_path
1349                 
1350                 full_path += ConfigurationFile::GetInstance().Get_file_separator();
1351                 full_path += upath;
1352                 
1353                 if ( Utilities::IsDirectory( full_path ) )
1354                   {
1355                     script_paths.push_back(full_path);
1356                   }
1357               } 
1358             if (script_paths.empty())
1359               {
1360                 bbtkError("no '"<<upath<<"' subdir found in search paths" 
1361                           << std::endl);
1362               }
1363           }
1364         
1365         // === search paths list complete : now explore it
1366         int nbBssFiles = 0;     
1367         // ==== relative name, iterate + load all .bbs/.bbp files
1368         std::vector<std::string>::iterator i;
1369         for (i=script_paths.begin();i!=script_paths.end();i++)
1370           {
1371                   
1372             bbtkMessage("interpreter",1,
1373                         "--> Looking in '" << *i << "'" << std::endl);
1374             
1375             Filenames.clear();
1376             //int nbFiles = 
1377             Utilities::Explore(*i, false, Filenames);
1378
1379                   int iFilesnames,jFilesnames,sizeFilenames;
1380                   sizeFilenames=Filenames.size();
1381                   
1382                   
1383                   // EEDd 30 sept 2012
1384                   //Sorting list of files
1385                   for (iFilesnames=0;iFilesnames<sizeFilenames; iFilesnames++)
1386               {
1387                           for (jFilesnames=iFilesnames;jFilesnames<sizeFilenames; jFilesnames++)
1388                           {
1389                                   if ( Filenames[iFilesnames] > Filenames[jFilesnames] )
1390                                   {
1391                                           tmpFilenames                          = Filenames[iFilesnames];
1392                                           Filenames[iFilesnames]        = Filenames[jFilesnames];
1393                                           Filenames[jFilesnames]        = tmpFilenames;
1394                                   } // if Filesnames
1395                           } // for iFilesnames
1396               } // for iFilesnames
1397                   
1398                   
1399                   
1400             for (std::vector<std::string>::iterator j = Filenames.begin(); 
1401                  j!= Filenames.end(); ++j)
1402               {
1403                 int lgr = (*j).size();
1404                 if (lgr < 5) continue;  
1405                 // ignore non .bbp file
1406                 if ( (*j).substr(lgr-4, 4) != ".bbp") continue; 
1407                 
1408                 (*stream) << "include \"" << *j << "\"\n";
1409                 bbtkMessage("interpreter",2,"  --> Found '" << *j << "'" << std::endl);
1410                 
1411                 nbBssFiles++;
1412               } // for (std::vector...
1413           } // for (i=script_...
1414
1415         // === Result ...
1416         if (nbBssFiles==0)
1417           {
1418             bbtkMessage("interpreter",1,
1419                         "  --> No .bbp found"<< std::endl);
1420           } 
1421         else 
1422           {
1423             bbtkMessage("interpreter",1,
1424                         "  --> "<<nbBssFiles<<" .bbp found"<< std::endl);
1425             SwitchToStream(stream);
1426           }
1427         return;
1428       }  
1429     //=============== end pkgname=="*" ===========
1430     
1431     
1432     // if name starts with a / or a . or contains : user is assumed to have passed a relative/absolute name
1433     // (not only a plain script name)
1434     // we trust him, and try to expland the directory name
1435     // WARNING : starting from current local directory :  ./whatYouWant  (./ mandatory!)
1436
1437     if (name[0]=='/' || name[1] == ':' || name[0]=='.')  // absolute path (linux/windows) or relative path
1438     { 
1439
1440       // ===========================================================check user supplied location
1441       fullnameGiven = true;
1442
1443       fullPathScriptName =  Utilities::ExpandLibName(name, false);
1444
1445       // allow user to always forget ".bbs"
1446       int l = fullPathScriptName.size();
1447
1448       if (l!=0) 
1449           {
1450          if ((fullPathScriptName.substr(l-4, 4) != ".bbs")&&
1451                          (fullPathScriptName.substr(l-4, 4) != ".bbp"))
1452          {
1453                         std::string tfullPathScriptName = fullPathScriptName + ".bbs";
1454                         if ( Utilities::FileExists(tfullPathScriptName) )
1455                         {
1456                                 fullPathScriptName = tfullPathScriptName;
1457                                 foundFile = true;
1458                         }
1459                         else 
1460                         {
1461                                 tfullPathScriptName = fullPathScriptName + ".bbp";
1462                                 if ( Utilities::FileExists(tfullPathScriptName) )
1463                                 {
1464                                         fullPathScriptName = tfullPathScriptName;
1465                                         foundFile = true;
1466                                 }
1467                         }
1468                  }
1469                  else 
1470                  {
1471                         if ( Utilities::FileExists(fullPathScriptName) )
1472                         {
1473                                 foundFile = true;
1474                         }
1475                  }
1476           } // endif l != 0
1477   }
1478   else
1479   // =============================== iterate on the paths
1480   {
1481       script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
1482       std::string path;
1483       std::vector<std::string>::iterator i;
1484       for (i=script_paths.begin();i!=script_paths.end();++i)
1485           {
1486                 path = *i;
1487                 // we *really* want '.' to be the current working directory
1488                 if (path == ".") 
1489                 {
1490                         char buf[2048]; // for getcwd
1491                         char * currentDir = getcwd(buf, 2048);
1492                         std::string cwd(currentDir);
1493                         path = currentDir;
1494                 }
1495           
1496                 std::string tfullPathScriptName = Utilities::MakePkgnameFromPath(path, name, false);
1497                   
1498 //Addition JCP tfullPathScriptName.size()>=4 
1499                 if(tfullPathScriptName.size()>=4){
1500                         if (tfullPathScriptName.substr(tfullPathScriptName.size()-4, 3)==".bb")
1501                         {
1502                           fullPathScriptName = tfullPathScriptName;
1503                                 if ( ! Utilities::FileExists(fullPathScriptName) )
1504                                 {
1505                                         // The following is *NOT* a debug time message :
1506                                         // It's a user intended message.
1507                                         // Please don't remove it.
1508                                         bbtkMessage("interpreter",2,
1509                                   "   [" <<fullPathScriptName <<"] : does not exist" 
1510                                   <<std::endl);
1511                                         continue;  // try next path
1512                                 }
1513                                 bbtkMessage("interpreter",2,
1514                                           "   [" <<fullPathScriptName 
1515                                           <<"] : found" <<std::endl);
1516                                 foundFile = true;
1517                                 break; // a script was found; we stop iterating
1518                         }
1519                         else 
1520                         {
1521                                 fullPathScriptName = tfullPathScriptName + ".bbs";
1522                                 // Check if library exists
1523                                 if ( ! Utilities::FileExists(fullPathScriptName) )
1524                                 {
1525                                         fullPathScriptName = tfullPathScriptName + ".bbp";
1526                                         if ( ! Utilities::FileExists(fullPathScriptName) )
1527                                         {
1528                                                 // The following is *NOT* a debug time message :
1529                                                 // It's a user intended message.
1530                                                 // Please don't remove it.
1531                                                 bbtkMessage("interpreter",2,
1532                                                 "   [" <<tfullPathScriptName <<".bbs/.bbp] : do not exist" 
1533                                                 <<std::endl);
1534                                                 continue;  // try next path
1535                                         }
1536                                 }
1537                                 bbtkMessage("interpreter",2,
1538                                   "   [" <<fullPathScriptName 
1539                                   <<"] : found" <<std::endl);
1540                                 foundFile = true;
1541                                 break; // a script was found; we stop iterating
1542                         }
1543                 }               
1544         } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
1545   }
1546
1547     if (!foundFile)
1548       {
1549         if (fullnameGiven)
1550           if(fullPathScriptName == "")
1551             bbtkError("Path ["<<upath<<"] doesn't exist");
1552           else
1553             bbtkError("Script ["<<fullPathScriptName<<"] not found");
1554         else
1555           bbtkError("No ["<<pkgname<<".bbs/.bbp] script found");
1556         return;
1557       } else {
1558                 LoadScript(fullPathScriptName,name);
1559                   if (source) 
1560                   {
1561                           // Over writing the fullpath of the bbp file.
1562                           SetCurrentFileName( fullPathScriptName );
1563                           SetTypeOfScript_Application();
1564                   }
1565         }    
1566                   
1567     return;
1568   }
1569   //=======================================================================
1570
1571         //=======================================================================
1572         void InterpreterVirtual::SetCurrentFileName(const std::string &fullPathScriptName)  // virtual 
1573         {
1574         }       
1575         //=======================================================================
1576         
1577         
1578         //=======================================================================
1579         void InterpreterVirtual::SetTypeOfScript_Application( )
1580         {
1581         }
1582         //=======================================================================
1583
1584         
1585   //=======================================================================
1586 void InterpreterVirtual::SwitchToStream( std::stringstream* stream )
1587 {
1588   bbtkDebugMessage("interpreter",4,"==> InterpreterVirtual::SwitchToStream()"
1589                    <<std::endl);
1590    mFile.push_back(stream);
1591     std::ostringstream buffer_name;
1592     bufferNb++;
1593     buffer_name << "buffer_" ;
1594
1595     if (mFileName.size()>0 )
1596     {
1597        buffer_name << mFileName.back() << "_" << mLine.back();
1598     }
1599     mFileName.push_back(buffer_name.str());
1600     mIncludeFileName.push_back(buffer_name.str());
1601     mLine.push_back(0);
1602 }
1603   //=======================================================================
1604
1605   //=======================================================================
1606
1607   void InterpreterVirtual::LoadScript( std::string fullPathScriptName,
1608                                 std::string includeScriptName)
1609   {
1610     bbtkDebugMessage("interpreter",4,"==> InterpreterVirtual::LoadScript("
1611                      <<fullPathScriptName<<")"
1612                      <<std::endl);
1613
1614     Utilities::replace( fullPathScriptName , 
1615                          INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
1616    
1617      if (find(mFileNameHistory.begin(),
1618               mFileNameHistory.end(),
1619               fullPathScriptName)!=mFileNameHistory.end())
1620      {
1621         return;
1622      }
1623
1624     std::ifstream* s;
1625     s = new std::ifstream;
1626     s->open(fullPathScriptName.c_str());
1627     if (!s->good())
1628     {
1629         bbtkError("Could not open file ["<<fullPathScriptName<<"]");
1630         return;
1631     }
1632
1633     bbtkMessage("interpreter",1,"   -->[" << fullPathScriptName 
1634                 << "] found" << std::endl);
1635
1636     mFile.push_back(s);
1637     mFileName.push_back(fullPathScriptName);
1638     mFileNameHistory.push_back(fullPathScriptName);
1639     mIncludeFileName.push_back(includeScriptName);
1640     mLine.push_back(0);
1641
1642     return;
1643   }
1644   //=======================================================================
1645
1646   //=======================================================================
1647   void InterpreterVirtual::CloseCurrentFile()
1648   {
1649     bbtkDebugMessage("interpreter",9,"==> InterpreterVirtual::CloseCurrentFile()"
1650                       <<std::endl);
1651
1652     if (mFile.size()==0)
1653     {
1654       bbtkDebugMessage("interpreter",9," -> no file left open"<<std::endl);
1655       return;
1656     }
1657
1658     bbtkDebugMessage("interpreter",9," Closing file '"<<mFileName.back()<<"'"<<std::endl);
1659
1660     std::ifstream* file = dynamic_cast<std::ifstream*>(mFile.back());
1661     if (file!=0) file->close();
1662
1663     delete mFile.back();
1664     mFile.pop_back();
1665     mFileName.pop_back();
1666     mIncludeFileName.pop_back();
1667     mLine.pop_back();
1668
1669     bbtkDebugMessage("interpreter",9," Remains "
1670                      <<mFile.size()
1671                      <<" open"<<std::endl);
1672     bbtkDebugMessage("interpreter",9,"<== InterpreterVirtual::CloseCurrentFile()"
1673                      <<std::endl);
1674   }
1675   //=======================================================================
1676
1677  //=======================================================================
1678   void InterpreterVirtual::CloseAllFiles()
1679   {
1680     bbtkDebugMessage("interpreter",9,"==> InterpreterVirtual::CloseAllFiles()"
1681                       <<std::endl);
1682
1683     while (mFile.size() != 0) 
1684     {
1685        CloseCurrentFile();
1686     }
1687     bbtkDebugMessage("interpreter",9,"<== InterpreterVirtual::CloseAllFiles()"
1688                       <<std::endl);
1689   }
1690   //=======================================================================
1691
1692
1693
1694   //=======================================================================
1695   void InterpreterVirtual::InterpretCommand( const std::vector<std::string>& words,
1696                                       CommandInfoType& info )
1697   {
1698           
1699     bbtkDebugMessage("interpreter",9,"==> InterpreterVirtual::InterpretCommand(...)"<<std::endl);
1700
1701     // searches the command keyword
1702     CommandDictType::iterator c;
1703     c = mCommandDict.find(words[0]);
1704     if ( c == mCommandDict.end() ) {
1705       bbtkError(words[0]<<" : unknown command");
1706     }
1707
1708     // tests the number of args 
1709     if ( ( ((int)words.size())-1 < c->second.argmin ) ||
1710          ( ((int)words.size())-1 > c->second.argmax ) )
1711     {
1712                 
1713 //EED       HelpCommand(words[0]);
1714                 commandHelp(words[0]);
1715        bbtkError(words[0]<<" : wrong number of arguments");
1716     }
1717 //std::cout<<"InterpreterVirtual::InterpretCommand( const std::vector<std::string>& words,"<<std::endl;
1718     info = c->second;
1719     bbtkDebugMessage("interpreter",9,"<== InterpreterVirtual::InterpretCommand(...)"<<std::endl);
1720
1721   }
1722   //=======================================================================
1723
1724
1725   //=======================================================================
1726   /// Displays help on all the commands
1727   void InterpreterVirtual::commandHelp(const std::vector<std::string>& words) 
1728   { 
1729   }
1730   //=======================================================================
1731   void InterpreterVirtual::commandHelp(const std::string &words) 
1732   {  
1733   }
1734         //=======================================================================
1735         
1736    //===================================================================    
1737   /// Displays the Configuration
1738   void InterpreterVirtual::commandConfig() const
1739   {
1740   }  
1741    //===================================================================    
1742
1743
1744
1745   //=======================================================================
1746   /// Fills the vector commands with the commands which 
1747   /// have the first n chars of buf for prefix
1748   /// TODO : skip initial spaces in buf and also return the position of first
1749   /// non blank char in buf
1750   void InterpreterVirtual::FindCommandsWithPrefix( char* buf,
1751                                             int n,
1752                                             std::vector<std::string>& commands )
1753   {
1754     CommandDictType::const_iterator i;
1755     for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1756     {
1757       if ((i->first).find(buf,0,n) == 0) 
1758         commands.push_back(i->first);
1759     }
1760   }
1761   //=======================================================================
1762
1763
1764
1765   //=======================================================================
1766 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1767   
1768   inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1769   inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1770   
1771   // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1772   // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1773   // E.G. STORE THIS IN bbtk_config.xml
1774 #define BBTK_UP_ARROW_KBCODE    0x00415B1B
1775 #define BBTK_DOWN_ARROW_KBCODE  0x00425B1B
1776 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1777 #define BBTK_LEFT_ARROW_KBCODE  0x00445B1B
1778 #define BBTK_BACKSPACE_KBCODE   0x00000008
1779 #define BBTK_DEL_KBCODE         0x0000007F
1780 #define BBTK_SPACE_KBCODE       0x00000020 
1781
1782   //=======================================================================
1783   void InterpreterVirtual::GetLineFromPrompt(std::string& s)
1784   {
1785     int c;
1786     unsigned int ind=0;
1787
1788     unsigned int MAX_LINE_SIZE = 160;
1789     unsigned int MAX_HISTORY_SIZE = 100;
1790
1791     char* newline = new char[MAX_LINE_SIZE];
1792     memset(newline,0,MAX_LINE_SIZE);
1793     char* histline = new char[MAX_LINE_SIZE];
1794     memset(histline,0,MAX_LINE_SIZE);
1795
1796     char* line = newline;
1797     unsigned int hist = mHistory.size();
1798
1799     write(1,"> ",2);
1800     while(1)
1801     {
1802        c=0;
1803        read ( STDIN_FILENO, &c, 4) ;
1804
1805        bbtkDebugMessage("debug",9,"[0x"<<std::hex<<c<<"]\n");
1806
1807        // Printable character
1808        if ( (ind<MAX_LINE_SIZE-1) &&
1809             ( c >= BBTK_SPACE_KBCODE ) && 
1810             ( c <  BBTK_DEL_KBCODE )) 
1811        {
1812           PrintChar(c);
1813           line[ind++]=c;
1814        }
1815       // CR
1816        else if (c=='\n')
1817        {
1818        // delete the unused line
1819           if (line==newline)
1820               delete histline;
1821           else
1822               delete newline;
1823    
1824     // empty lines are not stored in from history
1825           if (strlen(line)) 
1826           {
1827              // if history too long : delete oldest command
1828              if (mHistory.size()>MAX_HISTORY_SIZE) 
1829              {
1830                 delete mHistory.front();
1831                 mHistory.pop_front();
1832              }
1833              mHistory.push_back(line);
1834           }
1835           break;
1836         }
1837        // Backspace
1838         else if ( (ind>0) && 
1839                   ((c == BBTK_BACKSPACE_KBCODE) ||
1840                    (c == BBTK_DEL_KBCODE)) )
1841           {
1842             line[ind--]=' ';
1843             BackSpace();
1844           }
1845         // Tab 
1846         else if (c=='\t')
1847           {
1848             // TODO : Command completion  
1849             std::vector<std::string> commands;
1850             FindCommandsWithPrefix( line,ind,commands);
1851             if (commands.size()==1) 
1852               {
1853                 std::string com = *commands.begin();
1854                 for (; ind<com.size(); ++ind) 
1855                   {
1856                     PrintChar(com[ind]); 
1857                     line[ind]=com[ind];
1858                   }
1859                 PrintChar(' '); 
1860                 line[ind++]=' ';
1861               }
1862             else if (commands.size()>1) 
1863               {
1864                 std::vector<std::string>::iterator i;
1865                 write(1,"\n",1);
1866                 for (i=commands.begin();i!=commands.end();++i) 
1867                   {
1868                     write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1869                     PrintChar(' ');
1870                   }
1871                 write(STDOUT_FILENO,"\n> ",3);
1872                 //for (int j=0;j<ind;++j) 
1873                   //{
1874                     write(STDOUT_FILENO,line,ind); 
1875                     //  }
1876               }
1877           }
1878         // Arrow up : back in history
1879         else if (c==BBTK_UP_ARROW_KBCODE)
1880           {
1881             if (hist) 
1882               {
1883                 // erase current line
1884                 while (ind--) BackSpace();
1885                 // 
1886                 hist--;
1887                 // 
1888                 strcpy(histline,mHistory[hist]);
1889                 line = histline;
1890                 ind = strlen(line);
1891                 
1892                 write(STDOUT_FILENO,line,ind);
1893               }
1894           }
1895         // Arrow down : down in history
1896         else if (c==BBTK_DOWN_ARROW_KBCODE)
1897           {
1898             if (hist<mHistory.size()-1) 
1899               {
1900                 // erase current line
1901                 while (ind--) BackSpace();
1902                 // 
1903                 hist++;
1904                 // 
1905                 strcpy(histline,mHistory[hist]);
1906                 line = histline;
1907                 ind = strlen(line);
1908                 
1909                 write(STDOUT_FILENO,line,ind);
1910               }
1911             // end of history : switch back to newline
1912             else if (hist==mHistory.size()-1)
1913               {
1914                 // erase current line
1915                 while (ind--) BackSpace();
1916                 // 
1917                 hist++;
1918                 // 
1919                 line = newline;
1920                 ind = strlen(line);
1921                 
1922                 write(STDOUT_FILENO,line,ind);
1923               }
1924           }
1925         // Arrow right
1926         else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1927           {
1928             PrintChar(line[ind]);
1929             ind++;
1930           }
1931
1932         // Arrow left
1933         else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1934           {
1935             PrintChar('\b');
1936             ind--;
1937     
1938           }
1939
1940       }
1941     write(STDOUT_FILENO,"\n\r",2);
1942     
1943     
1944     s = line;
1945     
1946   }
1947 #else
1948
1949   //=======================================================================
1950   void InterpreterVirtual::GetLineFromPrompt(std::string& s)
1951   {  
1952     s.clear();
1953
1954     putchar('>');
1955     putchar(' ');
1956
1957     do 
1958     {
1959       char c = getchar();
1960       if (c=='\n') 
1961       {
1962         putchar('\n');
1963         break;
1964       }
1965       if (c=='\t') 
1966       {
1967         // putchar('T');
1968         continue;
1969       }
1970       // putchar(c);
1971       s += c;
1972     } 
1973     while (true);  
1974     
1975   }
1976   //=======================================================================  
1977
1978 #endif
1979
1980
1981
1982   //=======================================================================
1983   void InterpreterVirtual::CommandLineInterpreter()
1984   {
1985     bbtkDebugMessageInc("interpreter",9,
1986                         "InterpreterVirtual::CommandLineInterpreter()"<<std::endl);
1987
1988 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT  
1989     // Initialise the tty in non canonical mode with no echo
1990     // oter remembers the previous settings to restore them after 
1991     struct termios ter,oter;
1992     tcgetattr(0,&ter);
1993     oter=ter;
1994     ter.c_lflag &= ~ECHO;
1995     ter.c_lflag &= ~ICANON;
1996     ter.c_cc[VMIN]=1;
1997     ter.c_cc[VTIME]=0;
1998     tcsetattr(0,TCSANOW,&ter);
1999 #endif
2000
2001     mCommandLine = true;
2002     bool again = true;
2003     // bool insideComment = false; // for multiline comment  
2004     mInsideComment = false;
2005     do 
2006     {
2007       try
2008       {
2009         std::string line;
2010         GetLineFromPrompt(line);
2011         DoInterpretLine(line); //, insideComment);
2012       }
2013       /*
2014       catch (QuitException e)
2015       {
2016         bbtkMessage("interpreter",1,"Interpreter : Quit"<<std::endl);
2017         again = false;
2018       }
2019       */
2020       catch (bbtk::Exception e) 
2021       {
2022         e.Print();
2023       }
2024         catch (std::exception& e) 
2025       {
2026         std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
2027       }
2028       catch (...)
2029       {
2030         std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
2031       }
2032     }
2033     while (again);
2034
2035 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
2036     tcsetattr(0,TCSANOW,&oter);
2037 #endif
2038
2039     std::cout << "Good bye !" << std::endl;
2040
2041     bbtkDebugDecTab("interpreter",9);
2042   }
2043
2044 //=======================================================================
2045 void InterpreterVirtual::commandGraph(const std::vector<std::string>& words)
2046 {
2047 }
2048 //=======================================================================
2049
2050
2051 //=======================================================================
2052 void  InterpreterVirtual::commandIndex(const std::string& filename, const std::string& type)
2053 {
2054 }
2055 //=======================================================================
2056
2057
2058 //=======================================================================
2059 void  InterpreterVirtual::commandNewGUI(const std::string& boxname,const std::string& instanceName)
2060 {
2061 }
2062 //=======================================================================
2063
2064
2065
2066  //==========================================================================
2067   void InterpreterVirtual::commandDebug(const std::string& name)
2068   {
2069   }
2070  //==========================================================================
2071
2072   /*
2073   //==========================================================================
2074   // Adds a callback when 'break' command issued
2075   void InterpreterVirtual::AddBreakObserver( BreakCallbackType c )
2076   {
2077     mBreakSignal.connect(c);
2078   }
2079  //==========================================================================
2080  */
2081
2082  //==========================================================================
2083   std::string InterpreterVirtual::GetObjectName() const
2084   {
2085     return std::string("InterpreterVirtual");
2086   }
2087   //==========================================================================
2088   
2089   //==========================================================================
2090   std::string  InterpreterVirtual::GetObjectInfo() const 
2091   {
2092     std::stringstream i;
2093     return i.str();
2094   }
2095   //==========================================================================
2096
2097   //==========================================================================
2098 size_t  InterpreterVirtual::GetObjectSize() const 
2099 {
2100   size_t s = Superclass::GetObjectSize();
2101   s += InterpreterVirtual::GetObjectInternalSize();
2102   return s;
2103   }
2104   //==========================================================================
2105   //==========================================================================
2106 size_t  InterpreterVirtual::GetObjectInternalSize() const 
2107 {
2108   size_t s = sizeof(InterpreterVirtual);
2109   return s;
2110   }
2111   //==========================================================================
2112   //==========================================================================
2113   size_t  InterpreterVirtual::GetObjectRecursiveSize() const 
2114   {
2115     size_t s = Superclass::GetObjectRecursiveSize();
2116     s += InterpreterVirtual::GetObjectInternalSize();
2117     return s;
2118   }
2119   //==========================================================================
2120 }//namespace
2121
2122