]> Creatis software - bbtk.git/blob - kernel/src/bbtkExecuter.cxx
*** empty log message ***
[bbtk.git] / kernel / src / bbtkExecuter.cxx
1 /*=========================================================================                                                                               
2   Program:   bbtk
3   Module:    $RCSfile: bbtkExecuter.cxx,v $
4   Language:  C++
5   Date:      $Date: 2009/06/08 14:50:03 $
6   Version:   $Revision: 1.31 $
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 Executer: level 0 of script execution (code)
34  */
35
36 #include "bbtkExecuter.h"
37 #include "bbtkMessageManager.h"
38 #include "bbtkFactory.h"
39 #include "bbtkUtilities.h"
40 //#include "bbtkWx.h"
41 #include <fstream>
42
43 #ifdef USE_WXWIDGETS
44 #include <wx/textdlg.h>
45 #endif
46
47 #include "bbtkWxBlackBox.h"
48
49 #include "bbtkConfigurationFile.h"
50
51 namespace bbtk
52 {
53   //=======================================================================
54   Executer::Pointer Executer::New()
55   {
56     bbtkDebugMessage("object",9,"Executer::New()"<<std::endl);
57     return MakePointer(new Executer());
58   }
59   //=======================================================================
60
61   //=======================================================================
62   Executer::Executer()
63     : 
64     mFactory(),
65     mRootPackage(),
66     mRootCBB(),
67     mNoExecMode(false),
68     mDialogMode(NoDialog),
69     mNoErrorMode(false)
70   {
71     bbtkDebugMessage("object",2,"==> Executer()" <<std::endl);
72     mFactory = Factory::New();
73     // The smart pointer on this is not made yet (is made by New) 
74     // -> create it to pass it to the factory
75     // We have to "lock" the smart pointer because the factory
76     // only keeps a weak pointer on the executer
77     // -> this would auto-destroy !!
78     mFactory->SetExecuter(MakePointer(this,true));
79     Reset();
80     bbtkDebugMessage("object",2,"<== Executer()" <<std::endl);
81   }
82   //=======================================================================
83
84   //=======================================================================
85   Executer::~Executer()
86   {
87      bbtkDebugMessage("object",2,"==> ~Executer()" <<std::endl);
88      mOpenDefinition.clear();
89      mOpenPackage.clear();
90      mFactory->Reset();
91      mFactory.reset();
92      bbtkDebugMessage("object",2,"<== ~Executer()" <<std::endl);
93   }
94   //=======================================================================
95
96   //=======================================================================
97    /// Loads a package
98     void Executer::LoadPackage(const std::string &name )
99    {
100      GetFactory()->LoadPackage(name);
101    }
102   //=======================================================================
103
104   //=======================================================================
105     /// Unloads a package
106     void Executer::UnLoadPackage(const std::string &name )
107     {
108       GetFactory()->UnLoadPackage(name);
109     }
110   //=======================================================================
111
112   //=======================================================================
113   void Executer::Reset()
114   {
115     bbtkDebugMessage("kernel",9,"==> Executer::Reset()" <<std::endl);
116
117     //    GetFactory()->Check();
118  
119     mOpenDefinition.clear();
120     mOpenPackage.clear();
121
122     //  Wx::DestroyTopWindow();
123
124     GetFactory()->Reset();
125     Wx::ProcessPendingEvents();
126  
127     // Create user package
128     Package::Pointer p =
129       Package::New("user","internal","User defined black boxes","");
130     // Insert the user package in the factory
131     GetFactory()->InsertPackage(p);
132     // And in the list of open packages
133     mOpenPackage.push_back(p);
134     mRootPackage = p;
135
136     // Create user workspace
137     ComplexBlackBoxDescriptor::Pointer r = 
138       ComplexBlackBoxDescriptor::New("workspace"); 
139     //    mRootCBB->Reference();
140     r->SetFactory(GetFactory());
141     r->AddToAuthor("bbtk");
142     r->AddToDescription("User's workspace");
143     mOpenDefinition.push_back(CBBDefinition(r,"user"));
144     // Register it into the user package
145     p->Register(r);
146     mRootCBB = r;
147
148     //    Object::PrintObjectListInfo();
149     //  GetFactory()->CheckPackages();
150     bbtkDebugMessage("kernel",9,"<== Executer::Reset()" <<std::endl);
151   }
152   //=======================================================================
153
154
155   //=======================================================================
156   /// changes the workspace name
157   void Executer::SetWorkspaceName( const std::string& n )
158   {
159     GetUserPackage()->ChangeDescriptorName( GetWorkspace()->GetTypeName(), n );
160   }
161   //=======================================================================
162
163   //=======================================================================
164   void Executer::BeginPackage (const std::string &name)
165   {
166      bbtkDebugMessage("kernel",9,"==> Executer::BeginPackage(\""<<name<<"\")"
167                         <<std::endl);
168      Package::Pointer p;
169      try 
170       {
171          p = GetFactory()->GetPackage(name);
172       }
173     catch (Exception e)
174       {
175         p = Package::New(name,"","","");
176         GetFactory()->InsertPackage(p);
177       }
178      mOpenPackage.push_back(p);
179
180      bbtkDebugMessage("kernel",9,"<== Executer::BeginPackage(\""<<name<<"\")"
181                       <<std::endl);
182   }
183   //=======================================================================
184
185   //=======================================================================
186   void Executer::EndPackage()
187   {
188     if (mOpenPackage.size()>1) mOpenPackage.pop_back();
189   }
190   //=======================================================================
191
192   //=======================================================================
193   void Executer::Define (const std::string &name,
194                          const std::string &pack,
195                          const std::string &scriptfilename)
196   {
197     bbtkDebugMessage("kernel",9,"==> Executer::Define(\""<<name<<
198                      ","<<pack<<"\")"
199                      <<std::endl);
200
201     ComplexBlackBoxDescriptor::Pointer b 
202       = ComplexBlackBoxDescriptor::New(name);
203     b->SetFactory(GetFactory());
204     b->SetScriptFileName(scriptfilename);
205     mOpenDefinition.push_back( CBBDefinition( b, pack ) );
206     
207     bbtkDebugMessage("kernel",9,"<== Executer::Define(\""<<name<<
208                      ","<<pack<<"\")"
209                      <<std::endl);
210   }
211   //=======================================================================
212
213   //=======================================================================
214   /// Sets the file name to use for the current definition
215   /// (Used to set it after the Define command)
216   void Executer::SetCurrentFileName (const std::string &name )
217   {
218     mOpenDefinition.back().box->SetScriptFileName(name);
219   }
220   //=======================================================================
221
222   //=======================================================================
223   void Executer::Clear()
224   {
225     bbtkDebugMessage("kernel",9,"==> Executer::Clear()" <<std::endl);
226     GetCurrentDescriptor()->GetPrototype()->Clear();
227     bbtkDebugMessage("kernel",9,"<== Executer::Clear()" <<std::endl);
228   }
229   //=======================================================================
230
231   //=======================================================================
232   void Executer::EndDefine ()
233   {
234     bbtkDebugMessage("kernel",9,"==> Executer::EndDefine(\""
235                      <<GetCurrentDescriptor()->GetTypeName()<<"\")" 
236                      <<std::endl);
237     // Does current package exist ?
238     Package::Pointer p;
239     std::string pname(mOpenDefinition.back().package);
240     if (pname.size()>0)
241       {
242         try
243           {
244             p = GetFactory()->GetPackage(pname);
245           }
246         catch (Exception e)
247           {
248             p = Package::New(pname,"","","");
249             GetFactory()->InsertPackage(p);
250           }
251       }
252     else
253       {
254         p = mOpenPackage.back().lock();
255       }
256     // Register the descriptor in the current package
257     p->Register(GetCurrentDescriptor());
258     
259     bbtkDebugMessage("kernel",9,"<== Executer::EndDefine(\""
260                      <<GetCurrentDescriptor()->GetTypeName()<<"\")" 
261                      <<std::endl);
262     mOpenDefinition.pop_back();
263   }
264   //======================================================================= 
265
266   //=======================================================================  
267   void Executer::Kind(const std::string& kind)
268   {
269     if (kind=="ADAPTOR")
270       {
271         GetCurrentDescriptor()->AddToCategory("adaptor");
272         GetCurrentDescriptor()->SetKind(bbtk::BlackBoxDescriptor::ADAPTOR);
273       }
274     else if (kind=="DEFAULT_ADAPTOR")
275       {
276         GetCurrentDescriptor()->AddToCategory("adaptor");
277         GetCurrentDescriptor()->SetKind(bbtk::BlackBoxDescriptor::DEFAULT_ADAPTOR);
278       }
279     if (kind=="GUI")
280       {
281         GetCurrentDescriptor()->AddToCategory("gui");
282         GetCurrentDescriptor()->SetKind(bbtk::BlackBoxDescriptor::GUI);
283       }
284     else if (kind=="DEFAULT_GUI")
285       {
286         GetCurrentDescriptor()->AddToCategory("gui");
287         GetCurrentDescriptor()->SetKind(bbtk::BlackBoxDescriptor::DEFAULT_GUI);
288       }
289     else
290       {
291         bbtkError("Unknown box kind : '"<<kind<<"'. "
292                   <<"Valid kinds are 'ADAPTOR','DEFAULT_ADAPTOR',"
293                   <<"'GUI','DEFAULT_GUI'");
294       }
295   }
296   //=======================================================================
297
298   //=======================================================================
299   void Executer::Create ( const std::string& nodeType, 
300                           const std::string& nodeName)
301   {
302      GetCurrentDescriptor()->Add(nodeType,nodeName);
303   }
304   //=======================================================================
305
306   //=======================================================================
307   void Executer::Destroy(const std::string &boxName)
308   {
309     GetCurrentDescriptor()->Remove(boxName,true);
310   }
311   //=======================================================================
312
313   //=======================================================================
314   void Executer::Connect (const std::string &nodeFrom,
315                           const std::string &outputLabel,
316                           const std::string &nodeTo, 
317                           const std::string &inputLabel)
318   {
319     GetCurrentDescriptor()->Connect(nodeFrom, outputLabel, nodeTo, inputLabel);
320   }
321   //=======================================================================
322
323   //=======================================================================
324   void Executer::Execute (const std::string &nodeName) 
325   {
326     // if in root
327     if (GetCurrentDescriptor()==GetWorkspace()) 
328      {
329         if (!mNoExecMode) 
330         {
331            GetCurrentDescriptor()->GetPrototype()->bbGetBlackBox(nodeName)->bbExecute(true);
332         }
333      }
334      else 
335      {
336         GetCurrentDescriptor()->AddToExecutionList(nodeName) ;
337      }
338   }
339   //=======================================================================
340
341   //=======================================================================
342   void Executer::DefineInput ( const std::string &name,
343                                const std::string &box,
344                                const std::string &input,
345                                const std::string& help)
346   {
347     // If the input is defined in the Root box
348     if (GetCurrentDescriptor()==GetWorkspace()) 
349       {
350       // If the dialog mode is set to NoDialog
351       // and the user passed the name in the Inputs map 
352       // then the associated value is set to the box.input
353       // This is the way command line parameters are passed to the Root box
354          if (mDialogMode == NoDialog) 
355          {
356          // find if name is in mInputs
357             std::map<std::string,std::string>::iterator i;
358             i = mInputs.find(name);
359             if (i!=mInputs.end()) {
360                Set(box,input,(*i).second);
361             }
362          }
363         // If the dialog mode is set to TextDialog
364         // The user is prompted for the value
365         else if (mDialogMode == TextDialog) 
366         {
367            std::cout << name << "=";
368            std::string ans;
369            std::cin >> ans;
370            Set(box,input,ans);
371         }
372 #ifdef USE_WXWIDGETS
373        // If the dialog mode is set to GraphicalDialog
374        // A dialog box is pop up
375        else if (mDialogMode == GraphicalDialog) 
376        {
377           std::string mess("Enter the value of '");
378           mess += name;
379           mess += "' (";
380           mess += help;
381           mess += ")";
382           std::string title(name);
383           title += " ?";
384           std::string ans = wx2std ( wxGetTextFromUser( std2wx (mess), std2wx(title)));
385           Set(box,input,ans); 
386        }
387 #endif
388     }
389
390     GetCurrentDescriptor()->DefineInput(name,box,input,help);
391
392   }
393   //=======================================================================
394
395   //=======================================================================
396    void Executer::DefineOutput ( const std::string &name,
397                                  const std::string &box,
398                                  const std::string &output,
399                                  const std::string& help)
400   {
401     GetCurrentDescriptor()->DefineOutput(name,box,output,help);
402   }
403   //=======================================================================
404
405   //=======================================================================
406   void Executer::Set (const std::string &box,
407                       const std::string &input,
408                       const std::string &value)
409   {
410     BlackBox::Pointer b = GetCurrentDescriptor()->GetPrototype()->bbGetBlackBox(box);
411     // Looks for the adaptor
412
413     if ( ( b->bbGetInputType(input) != typeid(bbtk::any<bbtk::thing>) )&&
414          ( b->bbGetInputType(input) != typeid(std::string) ) )
415       {
416         BlackBox::Pointer a =
417            GetFactory()->NewAdaptor(typeid(std::string),
418                                     b->bbGetInputType(input),
419                                     "tmp");
420          if (!a) 
421            {
422              bbtkError("No <"<<
423                        TypeName(b->bbGetInputType(input))
424                        <<"> to <std::string> found");
425            }
426          std::string v(value);
427          a->bbSetInput("In",v);
428          a->bbExecute();
429          b->bbSetInput(input,a->bbGetOutput("Out"));
430          //         a->Delete();
431       }
432     else 
433       {
434       std::string v(value);
435       b->bbSetInput(input,v);
436       }
437   }
438   //=======================================================================
439
440   //=======================================================================
441   std::string Executer::Get(const std::string &box,
442                             const std::string &output)
443   {
444     BlackBox::Pointer b = GetCurrentDescriptor()->GetPrototype()->bbGetBlackBox(box);
445     // Looks for the adaptor
446     if (b->bbGetOutputType(output) != typeid(std::string)) 
447       {
448         BlackBox::Pointer a =
449           GetFactory()->NewAdaptor(
450                                    b->bbGetOutputType(output),
451                                    typeid(std::string),
452                                    "tmp");
453         if (!a) 
454           {
455             bbtkError("No <"<<
456                       TypeName(b->bbGetOutputType(output))
457                       <<"> to <std::string> found");
458           }
459         b->bbExecute();
460         
461         a->bbSetInput("In",b->bbGetOutput(output));
462         a->bbExecute();
463         std::string r = a->bbGetOutput("Out").unsafe_get<std::string>();
464         //std::string v = *((std::string*)a->bbGetOutput("Out")) ;
465         //   std::cout << a->bbGetOutput("Out").unsafe_get<std::string>() 
466         //             << std::endl;
467         //std::string v(value);
468         //b->bbSetInput(input,a->bbGetOutput("Out"));
469         //        a->bbDelete();
470         return r;
471       }
472     else
473       {
474         b->bbExecute();
475         return b->bbGetOutput(output).unsafe_get<std::string>();
476         // std::string v = *((std::string*)b->bbGetOutput(output)) ;
477         // std::cout << b->bbGetOutput("Out").unsafe_get<std::string>() 
478         //   << std::endl;
479         // b->bbSetInput(input,&v);
480       }
481   }
482   //=======================================================================
483
484   //=======================================================================
485   void Executer::Author(const std::string &authorName)
486   {
487     GetCurrentDescriptor()->AddToAuthor(authorName,GetCurrentDescriptor()==GetWorkspace());
488   }
489   //=======================================================================
490
491   //=======================================================================
492   void Executer::Category(const std::string &category)
493   {
494     GetCurrentDescriptor()->AddToCategory(category,GetCurrentDescriptor()==GetWorkspace());
495   }
496   //=======================================================================
497
498   //=======================================================================
499   void Executer::Description(const std::string &d)
500   {
501     GetCurrentDescriptor()->AddToDescription(d,GetCurrentDescriptor()==GetWorkspace());
502   }
503   //=======================================================================
504
505
506
507   //=======================================================================
508   /// prints the list of the boxes of the current descriptor
509   void Executer::PrintHelpListBoxes()
510   {
511     bbtkMessage("help",1,"The black box descriptor \""
512                 <<GetCurrentDescriptor()->GetTypeName()<<"\" contains : "<<std::endl);
513     GetCurrentDescriptor()->PrintBlackBoxes();
514  }
515   //=======================================================================
516
517   //=======================================================================
518   std::string Executer::ShowGraph(const std::string &nameblackbox, 
519                                   const std::string &detailStr, 
520                                   const std::string &levelStr,
521                                   const std::string &output_html,
522                                   const std::string &custom_header,
523                                   const std::string &custom_title,
524                                   bool system_display )
525   {
526     int detail  =       atoi(detailStr.c_str());
527     int level   =       atoi(levelStr.c_str());
528           bool relative_link = true;
529
530     Package::Pointer p;
531     try
532     {
533        p = GetFactory()->GetPackage(nameblackbox);
534     }
535     catch (Exception e)
536     {
537       p = GetUserPackage();
538     }
539           
540       std::string doc_path = bbtk::ConfigurationFile::GetInstance().Get_doc_path();
541       doc_path += bbtk::ConfigurationFile::GetInstance().Get_file_separator();
542       doc_path += "bbdoc";
543       doc_path += bbtk::ConfigurationFile::GetInstance().Get_file_separator();
544           
545           std::string pack_name(p->GetName());
546           std::string pack_path = doc_path + pack_name;
547           // Creating directory
548           if ( ! bbtk::Utilities::FileExists(pack_path) )
549           {
550                   std::string command("mkdir \"" +pack_path+ "\"");
551                   system( command.c_str() );
552           }
553           std::string pack_index(pack_path);
554           pack_index += bbtk::ConfigurationFile::GetInstance().Get_file_separator();
555           pack_index += "index.html"; 
556           
557           
558     // Generating documentation-help of workspace
559         p->SetDocURL(pack_index);
560     p->SetDocRelativeURL("index.html");
561         p->CreateHtmlPage(pack_index,"bbtk","user package",custom_header,custom_title,detail,level,relative_link);
562           
563     /*
564     try 
565     {
566        ShowGraphTypes(nameblackbox);
567     }
568     catch (bbtk::Exception a)
569     {
570        std::cout <<"EXC"<<std::endl;
571        page = ShowGraphInstances(nameblackbox,detail,level,system_display);
572     }
573     */
574     return pack_index;
575   }
576   //=======================================================================
577
578   //=======================================================================
579   /// Generate a png file with the actual pipeline (Graphviz-dot needed)
580   std::string Executer::ShowGraphInstances(const std::string &nameblackbox, int detail, int level,
581                                            bool system_display)
582   {
583
584     BlackBox::Pointer blackbox;
585     if (nameblackbox==".")
586     {
587        blackbox = GetCurrentDescriptor()->GetPrototype();
588     }
589     else
590     {
591        blackbox = GetCurrentDescriptor()->GetPrototype()->bbFindBlackBox(nameblackbox);
592     }
593     
594     std::string page;
595
596     if (blackbox)
597       {      
598         // Don't pollute the file store with  "temp_dir" directories ...
599         std::string default_doc_dir = ConfigurationFile::GetInstance().Get_default_temp_dir();
600         char c = default_doc_dir.c_str()[strlen(default_doc_dir.c_str())-1];
601
602         std::string directory = default_doc_dir; 
603         if (c != '/' && c !='\\') directory = directory + "/";
604
605         directory = directory +  "temp_dir";
606         //std::string directory("temp_dir");
607         std::string filename(directory + "/" + "bbtk_graph_pipeline");
608         std::string filename_html(filename+".html");
609         std::string command0("mkdir \""+directory + "\"");
610
611 #if defined(_WIN32)
612         std::string command2("start ");
613 #else 
614         std::string command2("gnome-open ");
615 #endif
616
617         command2=command2+filename_html;
618         page = filename_html;
619         // 1. Generate Html Diagram
620         std::ofstream s;
621         s.open(filename_html.c_str());
622         if (s.good()) 
623           {
624             s << "<html><head><title>BBtk graph diagram</title><meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\"></head>\n";
625             s << "<body bgcolor=\"#FFFFFF\" text=\"#000000\"> \n\n";
626             if ( blackbox->bbGetName()=="workspacePrototype" )
627               {
628                 s << "<center>Current workspace</center>";
629               } else {
630               s << "<center>" << blackbox->bbGetName()<< "</center>";
631             } 
632             blackbox->bbInsertHTMLGraph( s, detail, level, true, directory, false );
633             s << "</body></html>\n";
634           }
635         s.close();
636         
637         // 2. Starting Browser
638         if (system_display) system( command2.c_str() );      
639       } 
640     else 
641       {
642         bbtkMessage("help",1,"No black box: \""
643                     <<nameblackbox<<"\" " <<std::endl);
644       }
645     return page;
646   }
647   //=======================================================================
648
649   //=======================================================================
650   void Executer::PrintHelpBlackBox(const std::string &nameblackbox, 
651                                const std::string &detailStr, 
652                                const std::string &levelStr)
653   {
654     bool found=false;
655     
656     int detail = atoi(detailStr.c_str());
657     int level  = atoi(levelStr.c_str());
658     BlackBox::Pointer blackbox;
659     if (nameblackbox.compare(".")==0)
660       {
661         blackbox=GetCurrentDescriptor()->GetPrototype();
662       } 
663     else 
664       {
665         blackbox = GetCurrentDescriptor()->GetPrototype()->bbFindBlackBox(nameblackbox);
666       }
667     
668     if (blackbox)
669       {
670         found=true;
671         blackbox->bbPrintHelp(blackbox,detail,level); //,mFactory);
672       }
673     
674     if (!found) 
675       {
676         bbtkError("box with name '"  <<nameblackbox<<"' unknown");
677       }
678   }
679   //=======================================================================
680
681   //=======================================================================
682   /// sets the level of message
683   void Executer::SetMessageLevel(const std::string &kind,
684                                  int level)
685   {
686     bbtk::MessageManager::SetMessageLevel(kind,level);
687   }
688   //=======================================================================
689
690   //=======================================================================
691   /// Prints help on the messages
692   void  Executer::HelpMessages()
693   {
694     bbtk::MessageManager::PrintInfo();
695   }
696   //=======================================================================
697
698   //=======================================================================
699   ///
700   void Executer::Print(const std::string &str)
701   {  
702     if (GetNoExecMode() &&  (GetCurrentDescriptor()==GetWorkspace()) ) return;
703     if (GetCurrentDescriptor()!=GetWorkspace()) return;
704
705     bbtkDebugMessage("kernel",9,"Executer::Print(\""<<str<<"\")"<<std::endl);
706
707  // TO DO :
708  // InterpretLine ("load std")
709  // InterpretLine("new ConcatStrings _C_ ") -> trouver un nom unique : # commande 
710  // InterpretLine("new Print _P_") 
711  // InterpretLine("connect _C_.Out _P_.In")
712  // int num = 1
713  
714
715     std::vector<std::string> chains;
716     std::string delimiters("$");
717
718     // Skip delimiters at beginning.
719     std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
720     bool is_text = true;
721     if (lastPos>0) is_text = false;
722
723     // Find first delimiter.
724     std::string::size_type pos     = str.find_first_of(delimiters, lastPos);
725
726     while (std::string::npos != pos || std::string::npos != lastPos)
727     {
728        if (is_text) 
729        {
730           // Found a text token, add it to the vector.
731           chains.push_back(str.substr(lastPos, pos - lastPos));
732  // std::string token = str.substr(lastPos, pos - lastPos)
733  // InterpretLine("set _C_.In%num% %token%")
734  
735        }
736        else 
737        {
738
739        // is an output (between $$) : decode 
740          std::string tok,box,output;
741          tok = str.substr(lastPos, pos - lastPos);
742          Utilities::SplitAroundFirstDot(tok,box,output);
743          chains.push_back( Get(box,output) );
744
745 // InterpretLine("connect %tok% _C_.In%num%") 
746
747        }
748         // Skip delimiters.  Note the "not_of"
749        lastPos = str.find_first_not_of(delimiters, pos);
750         // Find next delimiter
751        pos = str.find_first_of(delimiters, lastPos);
752     //
753        is_text = !is_text;
754 // num ++;
755      }
756 // InterpretLine("exec _P_")
757 // if (IS_IN_WORKSPACE) InterpretLine("delete _C_; delete _P_");
758
759     std::vector<std::string>::iterator i;
760     for (i= chains.begin(); i!=chains.end(); ++i) 
761       {
762         Utilities::SubsBackslashN(*i);
763         bbtkMessage("output",1,*i);
764       }
765     bbtkMessage("output",1,std::endl);
766   }
767   //==========================================================================
768
769   //==========================================================================
770   std::string Executer::GetObjectName() const
771   {
772     return std::string("Executer");
773   }
774   //==========================================================================
775   
776   //==========================================================================
777   std::string  Executer::GetObjectInfo() const 
778   {
779     std::stringstream i;
780     return i.str();
781   }
782   //==========================================================================
783   //==========================================================================
784 size_t  Executer::GetObjectSize() const 
785 {
786   size_t s = Superclass::GetObjectSize();
787   s += Executer::GetObjectInternalSize();
788   return s;
789   }
790   //==========================================================================
791   //==========================================================================
792 size_t  Executer::GetObjectInternalSize() const 
793 {
794   size_t s = sizeof(Executer);
795   return s;
796   }
797   //==========================================================================
798   //==========================================================================
799   size_t  Executer::GetObjectRecursiveSize() const 
800   {
801     size_t s = Superclass::GetObjectRecursiveSize();
802     s += Executer::GetObjectInternalSize();
803     s += mFactory->GetObjectRecursiveSize();
804     return s;
805   }
806   //==========================================================================
807 }//namespace