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