TMacro.cxx

Go to the documentation of this file.
00001 // @(#)root/base:$Id: TMacro.cxx 35503 2010-09-21 06:34:34Z brun $
00002 // Author: Rene Brun   16/08/2005
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 
00013 //////////////////////////////////////////////////////////////////////////
00014 //                                                                      //
00015 // TMacro                                                               //
00016 //                                                                      //
00017 // Class supporting a collection of lines with C++ code.                //
00018 // A TMacro can be executed, saved to a ROOT file, edited, etc.         //
00019 //                                                                      //
00020 // A macro can be built line by line by calling the AddLine function.   //
00021 // or it can be created directly from a file via the special constructor//
00022 // when the first argument is a file name.                              //
00023 //                                                                      //
00024 // A macro can be executed via the Exec function.                       //
00025 // Arguments can be specified when calling Exec.                        //
00026 //                                                                      //
00027 // A macro can be drawn in a pad. When the pad is updated, the macro is //
00028 // automatically executed.                                              //
00029 //                                                                      //
00030 // The code in the macro can be saved via the SaveSource function.      //
00031 // If the macro is in the list of primitives of a pad/canvas, the macro //
00032 // will be saved in the script generated by TCanvas::SaveSource.        //
00033 //                                                                      //
00034 // A macro can be written to a ROOT file via TObject::Write.            //
00035 //                                                                      //
00036 // Examples:                                                            //
00037 //   TMacro m("Peaks.C");  //macro m with name "Peaks" is created       //
00038 //                         //from file  Peaks.C                         //
00039 //   m.Exec();             //macro executed with default arguments      //
00040 //   m.Exec("4");          //macro executed with argument               //
00041 //   m.SaveSource("newPeaks.C");                                        //
00042 //   TFile f("mymacros.root","recreate");                               //
00043 //   m.Write();   //macro saved to file with name "Peaks"               //
00044 //                                                                      //
00045 //////////////////////////////////////////////////////////////////////////
00046 
00047 #include "Riostream.h"
00048 #include "TEnv.h"
00049 #include "TList.h"
00050 #include "TMacro.h"
00051 #include "TMD5.h"
00052 #include "TObjString.h"
00053 #include "TROOT.h"
00054 #include "TSystem.h"
00055 
00056 ClassImp(TMacro)
00057 
00058 //______________________________________________________________________________
00059 TMacro::TMacro(): TNamed(), fLines(0)
00060 {
00061    // Create an empty macro, use AddLine() or ReadFile() to fill this macro.
00062 }
00063 
00064 //______________________________________________________________________________
00065 TMacro::TMacro(const char *name, const char *title): TNamed(name,title)
00066 {
00067    // Create a macro with a name and a title.
00068    // If name contains a '.' it is assumed to be the name of a file, and
00069    // * the macro is automatically filled by reading all the lines in the file,
00070    // * if the title is empty, it will be set to the name of the file,
00071    // * the name will be set to the filename without path or extension.
00072 
00073    fLines  = new TList();
00074    if (!name) return;
00075    Int_t nch = strlen(name);
00076    char *s = new char[nch+1];
00077    strlcpy(s,name,nch+1);
00078    char *slash = (char*)strrchr(s,'/');
00079    if (!slash) slash = s;
00080    else ++slash;
00081    char *dot   = (char*)strchr(slash,'.');
00082    if (dot) {
00083       *dot = 0;
00084       fName = slash;
00085       if (fTitle.Length() == 0) fTitle = name;
00086       ReadFile(name);
00087    }
00088    delete [] s;
00089 }
00090 
00091 //______________________________________________________________________________
00092 TMacro::TMacro(const TMacro &macro): TNamed(macro)
00093 {
00094    // Copy constructor.
00095 
00096    fLines = new TList();
00097    TIter next(macro.GetListOfLines());
00098    TObjString *obj;
00099    while ((obj = (TObjString*) next())) {
00100       fLines->Add(new TObjString(obj->GetName()));
00101    }
00102    fParams = macro.fParams;
00103 }
00104 
00105 //______________________________________________________________________________
00106 TMacro::~TMacro()
00107 {
00108    // Delete this macro.
00109 
00110    if (fLines) fLines->Delete();
00111    delete fLines;
00112 }
00113 
00114 //______________________________________________________________________________
00115 TMacro& TMacro::operator=(const TMacro &macro)
00116 {
00117    // Copy constructor.
00118 
00119    if(this!=&macro) {
00120       TNamed::operator=(macro);
00121       if (fLines) fLines->Delete();
00122       delete fLines;
00123       fLines = new TList();
00124       TIter next(macro.GetListOfLines());
00125       TObjString *obj;
00126       while ((obj = (TObjString*) next())) {
00127          fLines->Add(new TObjString(obj->GetName()));
00128       }
00129       fParams = macro.fParams;
00130    }
00131    return *this;
00132 }
00133 
00134 //______________________________________________________________________________
00135 TObjString *TMacro::AddLine(const char *text)
00136 {
00137    // Add line with text in the list of lines of this macro.
00138 
00139    if (!fLines) fLines = new TList();
00140    TObjString *obj = new TObjString(text);
00141    fLines->Add(obj);
00142    return obj;
00143 }
00144 
00145 //______________________________________________________________________________
00146 void TMacro::Browse(TBrowser * /*b*/)
00147 {
00148    // When clicking in the browser, the following action is performed
00149    // on this macro, depending the content of the variable TMacro.Browse.
00150    // TMacro.Browse can be set in the system.rootrc or .rootrc file like
00151    //     TMacro.Browse   :  Action
00152    // or set via gEnv->SetValue, eg
00153    //     gEnv->SetValue("TMacro.Browse","Print");
00154    // By default TMacro.Browse=""
00155    // -if TMacro.Browse ="" the macro is executed
00156    // -if TMacro.Browse ="Print" the macro is printed in stdout
00157    // -if TMacro.Browse is of the form "mymacro.C"
00158    //     the macro void mymacro.C(TMacro *m) is called where m=this macro
00159    //     An example of macro.C saving the macro into a file and viewing it
00160    //     with emacs is shown below:
00161    //        void mymacro(TMacro *m) {
00162    //           m->SaveSource("xx.log");
00163    //           gSystem->Exec("emacs xx.log&");
00164    //        }
00165 
00166    TString opt = gEnv->GetValue("TMacro.Browse","");
00167    if (opt.IsNull()) {
00168       Exec();
00169       return;
00170    }
00171    if (opt == "Print") {
00172       Print();
00173       return;
00174    }
00175    if (opt.Contains(".C")) {
00176       const char *cmd = Form(".x %s((TMacro*)0x%lx)",opt.Data(),(ULong_t)this);
00177       gROOT->ProcessLine(cmd);
00178       return;
00179    }
00180 }
00181 
00182 //______________________________________________________________________________
00183 TMD5 *TMacro::Checksum()
00184 {
00185    // Returns checksum of the current content. The returned TMD5 object must
00186    // be deleted by the user. Returns 0 in case of error.
00187 
00188    if (!fLines || fLines->GetSize() <= 0)
00189       return (TMD5 *)0;
00190 
00191    TMD5 *md5 = new TMD5;
00192 
00193    // Fill (same params as in TMD5::FileChecksum)
00194    const Int_t bufSize = 8192;
00195    UChar_t buf[bufSize];
00196    Long64_t pos = 0;
00197    Long64_t left = bufSize;
00198 
00199    TIter nxl(fLines);
00200    TObjString *l;
00201    while ((l = (TObjString *) nxl())) {
00202       TString line = l->GetString();
00203       line += '\n';
00204       Int_t len = line.Length();
00205       char *p = (char *) line.Data();
00206       if (left > len) {
00207          strlcpy((char *)&buf[pos], p, len+1);
00208          pos += len;
00209          left -= len;
00210       } else if (left == len) {
00211          strlcpy((char *)&buf[pos], p, len+1);
00212          md5->Update(buf, bufSize);
00213          pos = 0;
00214          left = bufSize;
00215       } else {
00216          strlcpy((char *)&buf[pos], p, left+1);
00217          md5->Update(buf, bufSize);
00218          len -= left;
00219          p += left;
00220          pos = 0;
00221          left = bufSize;
00222          strlcpy((char *)&buf[pos], p, len+1);
00223          pos += len;
00224          left -= len;
00225       }
00226    }
00227    md5->Update(buf, pos);
00228 
00229    // Finalize
00230    md5->Final();
00231 
00232    return md5;
00233 }
00234 
00235 //______________________________________________________________________________
00236 Long_t TMacro::Exec(const char *params, Int_t* error)
00237 {
00238    // Execute this macro with params, if params is 0, default parameters
00239    // (set via SetParams) are used.
00240    // error is set to an TInterpreter::EErrorCode by TApplication::ProcessLine().
00241    // Returns the result of the macro (return value or value of the last
00242    // expression), cast to a Long_t.
00243 
00244    //the current implementation uses a file in the current directory.
00245    //should be replaced by a direct execution from memory by CINT
00246    TString fname = GetName();
00247    fname += ".Cexec";
00248    SaveSource(fname);
00249    //disable a possible call to gROOT->Reset from the executed script
00250    gROOT->SetExecutingMacro(kTRUE);
00251    //execute script in /tmp
00252    TString exec = ".x " + fname;
00253    TString p = params;
00254    if (p == "") p = fParams;
00255    if (p != "")
00256       exec += "(" + p + ")";
00257    Long_t ret = gROOT->ProcessLine(exec, error);
00258    //enable gROOT->Reset
00259    gROOT->SetExecutingMacro(kFALSE);
00260    //delete the temporary file
00261    gSystem->Unlink(fname);
00262 
00263    return ret;
00264 }
00265 
00266 //______________________________________________________________________________
00267 TObjString *TMacro::GetLineWith(const char *text) const
00268 {
00269    // Search the first line containing text.
00270 
00271    if (!fLines) return 0;
00272    TIter next(fLines);
00273    TObjString *obj;
00274    while ((obj = (TObjString*) next())) {
00275       if (strstr(obj->GetName(),text)) return obj;
00276    }
00277    return 0;
00278 }
00279 
00280 //______________________________________________________________________________
00281 void TMacro::Paint(Option_t *option)
00282 {
00283    // Execute this macro (called by TPad::Paint).
00284 
00285    Exec(option);
00286 }
00287 
00288 //______________________________________________________________________________
00289 void TMacro::Print(Option_t * /*option*/) const
00290 {
00291    // Print contents of this macro.
00292 
00293    if (!fLines) return;
00294    TIter next(fLines);
00295    TObjString *obj;
00296    while ((obj = (TObjString*) next())) {
00297       printf("%s\n",obj->GetName());
00298    }
00299 }
00300 
00301 //______________________________________________________________________________
00302 Int_t TMacro::ReadFile(const char *filename)
00303 {
00304    // Read lines in filename in this macro.
00305 
00306    if (!fLines) fLines = new TList();
00307    ifstream in;
00308    in.open(filename);
00309    if (!in.good()) {
00310       Error("ReadFile","Cannot open file: %s",filename);
00311       return 0;
00312    }
00313    char *line = new char[10000];
00314    Int_t nlines = 0;
00315    while (1) {
00316       in.getline(line,10000);
00317       if (!in.good()) break;
00318       if (in.eof()) break;
00319       fLines->Add(new TObjString(line));
00320       nlines++;
00321    }
00322    delete [] line;
00323    return nlines;
00324 }
00325 
00326 //______________________________________________________________________________
00327 void TMacro::SaveSource(const char *filename)
00328 {
00329    // Save macro source in filename.
00330 
00331    ofstream out;
00332    out.open(filename, ios::out);
00333    if (!out.good ()) {
00334       Printf("SaveSource cannot open file: %s",filename);
00335       return;
00336    }
00337    if (!fLines) {out.close(); return;}
00338    TIter next(fLines);
00339    TObjString *obj;
00340    while ((obj = (TObjString*) next())) {
00341       out<<obj->GetName()<<endl;
00342    }
00343    out.close();
00344 }
00345 
00346 //______________________________________________________________________________
00347 void TMacro::SavePrimitive(ostream &out, Option_t *option /*= ""*/)
00348 {
00349    // Save macro source on stream out.
00350 
00351    char quote = '"';
00352    out<<"   "<<endl;
00353    if (gROOT->ClassSaved(TMacro::Class())) {
00354       out<<"   ";
00355    } else {
00356       out<<"   "<<ClassName()<<" *";
00357    }
00358    out<<"macro = new "<<ClassName()<<"("<<quote<<GetName()<<quote<<","<<quote<<GetTitle()<<quote<<");"<<endl;
00359    if (!fLines) return;
00360    TIter next(fLines);
00361    TObjString *obj;
00362    while ((obj = (TObjString*) next())) {
00363       TString s = obj->GetName();
00364       s.ReplaceAll("\"","\\\"");
00365       out<<"   macro->AddLine("<<quote<<s.Data()<<quote<<");"<<endl;
00366    }
00367    out<<"   macro->Draw("<<quote<<option<<quote<<");"<<endl;
00368 }
00369 
00370 //______________________________________________________________________________
00371 void TMacro::SetParams(const char *params)
00372 {
00373    // Set default parameters to execute this macro.
00374 
00375    if (params) fParams = params;
00376 }

Generated on Tue Jul 5 14:11:21 2011 for ROOT_528-00b_version by  doxygen 1.5.1