ROOT  6.06/09
Reference Guide
TMacro.cxx
Go to the documentation of this file.
1 // @(#)root/base:$Id$
2 // Author: Rene Brun 16/08/2005
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /** \class TMacro
13 
14 Class supporting a collection of lines with C++ code.
15 A TMacro can be executed, saved to a ROOT file, edited, etc.
16 
17 A macro can be built line by line by calling the AddLine function.
18 or it can be created directly from a file via the special constructor
19 when the first argument is a file name.
20 
21 A macro can be executed via the Exec function.
22 Arguments can be specified when calling Exec.
23 
24 A macro can be drawn in a pad. When the pad is updated, the macro is
25 automatically executed.
26 
27 The code in the macro can be saved via the SaveSource function.
28 If the macro is in the list of primitives of a pad/canvas, the macro
29 will be saved in the script generated by TCanvas::SaveSource.
30 
31 A macro can be written to a ROOT file via TObject::Write.
32 
33 Examples:
34 ~~~ {.cpp}
35  TMacro m("Peaks.C"); //macro m with name "Peaks" is created
36  //from file Peaks.C
37  m.Exec(); //macro executed with default arguments
38  m.Exec("4"); //macro executed with argument
39  m.SaveSource("newPeaks.C");
40  TFile f("mymacros.root","recreate");
41  m.Write(); //macro saved to file with name "Peaks"
42 ~~~
43 */
44 
45 #include "Riostream.h"
46 #include "TEnv.h"
47 #include "TList.h"
48 #include "TMacro.h"
49 #include "TMD5.h"
50 #include "TObjString.h"
51 #include "TROOT.h"
52 #include "TSystem.h"
53 #include <sstream>
54 
56 
57 ////////////////////////////////////////////////////////////////////////////////
58 /// Create an empty macro, use AddLine() or ReadFile() to fill this macro.
59 
60 TMacro::TMacro(): TNamed(), fLines(0)
61 {
62 }
63 
64 ////////////////////////////////////////////////////////////////////////////////
65 /// Create a macro with a name and a title.
66 /// If name contains a '.' it is assumed to be the name of a file, and
67 /// - the macro is automatically filled by reading all the lines in the file,
68 /// - if the title is empty, it will be set to the name of the file,
69 /// - the name will be set to the filename without path or extension.
70 
71 TMacro::TMacro(const char *name, const char *title): TNamed(name,title)
72 {
73  fLines = new TList();
74  if (!name) return;
75  Int_t nch = strlen(name);
76  char *s = new char[nch+1];
77  strlcpy(s,name,nch+1);
78  char *slash = (char*)strrchr(s,'/');
79  if (!slash) slash = s;
80  else ++slash;
81  char *dot = (char*)strchr(slash,'.');
82  if (dot) {
83  *dot = 0;
84  fName = slash;
85  if (fTitle.Length() == 0) fTitle = name;
86  ReadFile(name);
87  }
88  delete [] s;
89 }
90 
91 ////////////////////////////////////////////////////////////////////////////////
92 /// Copy constructor.
93 
94 TMacro::TMacro(const TMacro &macro): TNamed(macro)
95 {
96  fLines = new TList();
97  TIter next(macro.GetListOfLines());
98  TObjString *obj;
99  while ((obj = (TObjString*) next())) {
100  fLines->Add(new TObjString(obj->GetName()));
101  }
102  fParams = macro.fParams;
103 }
104 
105 ////////////////////////////////////////////////////////////////////////////////
106 /// Delete this macro.
107 
109 {
110  if (fLines) fLines->Delete();
111  delete fLines;
112 }
113 
114 ////////////////////////////////////////////////////////////////////////////////
115 /// Copy constructor.
116 
118 {
119  if(this!=&macro) {
120  TNamed::operator=(macro);
121  if (fLines) fLines->Delete();
122  delete fLines;
123  fLines = new TList();
124  TIter next(macro.GetListOfLines());
125  TObjString *obj;
126  while ((obj = (TObjString*) next())) {
127  fLines->Add(new TObjString(obj->GetName()));
128  }
129  fParams = macro.fParams;
130  }
131  return *this;
132 }
133 
134 ////////////////////////////////////////////////////////////////////////////////
135 /// Add line with text in the list of lines of this macro.
136 
138 {
139  if (!fLines) fLines = new TList();
140  TObjString *obj = new TObjString(text);
141  fLines->Add(obj);
142  return obj;
143 }
144 
145 ////////////////////////////////////////////////////////////////////////////////
146 /// When clicking in the browser, the following action is performed
147 /// on this macro, depending the content of the variable TMacro.Browse.
148 /// TMacro.Browse can be set in the system.rootrc or .rootrc file like:
149 /// ~~~ {.cpp}
150 /// TMacro.Browse : Action
151 /// ~~~
152 /// or set via gEnv->SetValue, eg
153 /// ~~~ {.cpp}
154 /// gEnv->SetValue("TMacro.Browse","Print");
155 /// ~~~
156 /// By default TMacro.Browse=""
157 /// -if TMacro.Browse ="" the macro is executed
158 /// -if TMacro.Browse ="Print" the macro is printed in stdout
159 /// -if TMacro.Browse is of the form "mymacro.C"
160 /// the macro void mymacro.C(TMacro *m) is called where m=this macro
161 /// An example of macro.C saving the macro into a file and viewing it
162 /// with emacs is shown below:
163 /// ~~~ {.cpp}
164 /// void mymacro(TMacro *m) {
165 /// m->SaveSource("xx.log");
166 /// gSystem->Exec("emacs xx.log&");
167 /// }
168 /// ~~~
169 
171 {
172  TString opt = gEnv->GetValue("TMacro.Browse","");
173  if (opt.IsNull()) {
174  Exec();
175  return;
176  }
177  if (opt == "Print") {
178  Print();
179  return;
180  }
181  if (opt.Contains(".C")) {
182  const char *cmd = Form(".x %s((TMacro*)0x%lx)",opt.Data(),(ULong_t)this);
183  gROOT->ProcessLine(cmd);
184  return;
185  }
186 }
187 
188 ////////////////////////////////////////////////////////////////////////////////
189 /// Returns checksum of the current content. The returned TMD5 object must
190 /// be deleted by the user. Returns 0 in case of error.
191 
193 {
194  if (!fLines || fLines->GetSize() <= 0)
195  return (TMD5 *)0;
196 
197  TMD5 *md5 = new TMD5;
198 
199  // Fill (same params as in TMD5::FileChecksum)
200  const Int_t bufSize = 8192;
201  UChar_t buf[bufSize];
202  Long64_t pos = 0;
203  Long64_t left = bufSize;
204 
205  TIter nxl(fLines);
206  TObjString *l;
207  while ((l = (TObjString *) nxl())) {
208  TString line = l->GetString();
209  line += '\n';
210  Int_t len = line.Length();
211  char *p = (char *) line.Data();
212  if (left > len) {
213  strlcpy((char *)&buf[pos], p, len+1);
214  pos += len;
215  left -= len;
216  } else if (left == len) {
217  strlcpy((char *)&buf[pos], p, len+1);
218  md5->Update(buf, bufSize);
219  pos = 0;
220  left = bufSize;
221  } else {
222  strlcpy((char *)&buf[pos], p, left+1);
223  md5->Update(buf, bufSize);
224  len -= left;
225  p += left;
226  pos = 0;
227  left = bufSize;
228  strlcpy((char *)&buf[pos], p, len+1);
229  pos += len;
230  left -= len;
231  }
232  }
233  md5->Update(buf, pos);
234 
235  // Finalize
236  md5->Final();
237 
238  return md5;
239 }
240 
241 ////////////////////////////////////////////////////////////////////////////////
242 /// Load the macro into the interpreter.
243 /// Return true in case the loading was successful.
244 
246 {
247  std::stringstream ss;
248 
249  TIter next(fLines);
250  TObjString *obj;
251  while ((obj = (TObjString*) next())) {
252  ss << obj->GetName() << std::endl;
253  }
254  return gInterpreter->LoadText(ss.str().c_str());
255 }
256 
257 ////////////////////////////////////////////////////////////////////////////////
258 /// Execute this macro with params, if params is 0, default parameters
259 /// (set via SetParams) are used.
260 /// error is set to an TInterpreter::EErrorCode by TApplication::ProcessLine().
261 /// Returns the result of the macro (return value or value of the last
262 /// expression), cast to a Long_t.
263 
264 Long_t TMacro::Exec(const char *params, Int_t* error)
265 {
266  if ( !gROOT->GetGlobalFunction(GetName(), 0, kTRUE) ) {
267  if (!Load()) {
268  if (error) *error = 1;
269  return 0;
270  }
271  }
272 
273  // if macro has been executed, look for global function with name
274  // of macro and re-execute this global function, if not found then
275  // macro is unnamed macro, which we re-execute from file
276  if ( gROOT->GetGlobalFunction(GetName(), 0, kTRUE) ) {
277  gROOT->SetExecutingMacro(kTRUE);
278  TString exec = GetName();
279  TString p = params;
280  if (p == "") p = fParams;
281  if (p != "")
282  exec += "(" + p + ")";
283  else
284  exec += "()";
285  Long_t ret = gROOT->ProcessLine(exec, error);
286  //enable gROOT->Reset
287  gROOT->SetExecutingMacro(kFALSE);
288  return ret;
289  }
290 
291  Error("Exec","Macro does not contains function named %s.",GetName());
292  if (error) *error = 1;
293  return 0;
294 }
295 
296 ////////////////////////////////////////////////////////////////////////////////
297 /// Search the first line containing text.
298 
300 {
301  if (!fLines) return 0;
302  TIter next(fLines);
303  TObjString *obj;
304  while ((obj = (TObjString*) next())) {
305  if (strstr(obj->GetName(),text)) return obj;
306  }
307  return 0;
308 }
309 
310 ////////////////////////////////////////////////////////////////////////////////
311 /// Execute this macro (called by TPad::Paint).
312 
313 void TMacro::Paint(Option_t *option)
314 {
315  Exec(option);
316 }
317 
318 ////////////////////////////////////////////////////////////////////////////////
319 /// Print contents of this macro.
320 
321 void TMacro::Print(Option_t * /*option*/) const
322 {
323  if (!fLines) return;
324  TIter next(fLines);
325  TObjString *obj;
326  while ((obj = (TObjString*) next())) {
327  printf("%s\n",obj->GetName());
328  }
329 }
330 
331 ////////////////////////////////////////////////////////////////////////////////
332 /// Read lines in filename in this macro.
333 
335 {
336  if (!fLines) fLines = new TList();
337  std::ifstream in;
338  in.open(filename);
339  if (!in.good()) {
340  Error("ReadFile","Cannot open file: %s",filename);
341  return 0;
342  }
343  char *line = new char[10000];
344  Int_t nlines = 0;
345  while (1) {
346  in.getline(line,10000);
347  if (!in.good()) break;
348  if (in.eof()) break;
349  fLines->Add(new TObjString(line));
350  nlines++;
351  }
352  delete [] line;
353  return nlines;
354 }
355 
356 ////////////////////////////////////////////////////////////////////////////////
357 /// Save macro source in filename.
358 
359 void TMacro::SaveSource(const char *filename)
360 {
361  std::ofstream out;
362  out.open(filename, std::ios::out);
363  if (!out.good ()) {
364  Printf("SaveSource cannot open file: %s",filename);
365  return;
366  }
367  if (!fLines) {out.close(); return;}
368  TIter next(fLines);
369  TObjString *obj;
370  while ((obj = (TObjString*) next())) {
371  out<<obj->GetName()<<std::endl;
372  }
373  out.close();
374 }
375 
376 ////////////////////////////////////////////////////////////////////////////////
377 /// Save macro source in file pointer fp.
378 
379 void TMacro::SaveSource(FILE *fp)
380 {
381  if (!fLines) {fclose(fp); return;}
382  TIter next(fLines);
383  TObjString *obj;
384  while ((obj = (TObjString*) next())) {
385  fprintf(fp, "%s\n", obj->GetName());
386  }
387  fclose(fp);
388 }
389 
390 ////////////////////////////////////////////////////////////////////////////////
391 /// Save macro source on stream out.
392 
393 void TMacro::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
394 {
395  char quote = '"';
396  out<<" "<<std::endl;
397  if (gROOT->ClassSaved(TMacro::Class())) {
398  out<<" ";
399  } else {
400  out<<" "<<ClassName()<<" *";
401  }
402  out<<"macro = new "<<ClassName()<<"("<<quote<<GetName()<<quote<<","<<quote<<GetTitle()<<quote<<");"<<std::endl;
403  if (!fLines) return;
404  TIter next(fLines);
405  TObjString *obj;
406  while ((obj = (TObjString*) next())) {
407  TString s = obj->GetName();
408  s.ReplaceAll("\"","\\\"");
409  out<<" macro->AddLine("<<quote<<s.Data()<<quote<<");"<<std::endl;
410  }
411  out<<" macro->Draw("<<quote<<option<<quote<<");"<<std::endl;
412 }
413 
414 ////////////////////////////////////////////////////////////////////////////////
415 /// Set default parameters to execute this macro.
416 
417 void TMacro::SetParams(const char *params)
418 {
419  if (params) fParams = params;
420 }
const char * GetName() const
Returns name of object.
Definition: TObjString.h:42
TString fTitle
Definition: TNamed.h:37
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:52
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:404
long long Long64_t
Definition: RtypesCore.h:69
void Final()
MD5 finalization, ends an MD5 message-digest operation, writing the the message digest and zeroizing ...
Definition: TMD5.cxx:165
ClassImp(TSeqCollection) Int_t TSeqCollection TIter next(this)
Return index of object in collection.
Ssiz_t Length() const
Definition: TString.h:390
TLine * line
Collectable string class.
Definition: TObjString.h:32
const char Option_t
Definition: RtypesCore.h:62
ClassImp(TMacro) TMacro
Create an empty macro, use AddLine() or ReadFile() to fill this macro.
Definition: TMacro.cxx:55
virtual void Paint(Option_t *option="")
Execute this macro (called by TPad::Paint).
Definition: TMacro.cxx:313
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:635
static const char * filename()
virtual Long_t Exec(const char *params=0, Int_t *error=0)
Execute this macro with params, if params is 0, default parameters (set via SetParams) are used...
Definition: TMacro.cxx:264
#define gROOT
Definition: TROOT.h:340
Class supporting a collection of lines with C++ code.
Definition: TMacro.h:33
Basic string class.
Definition: TString.h:137
virtual void Print(Option_t *option="") const
Print contents of this macro.
Definition: TMacro.cxx:321
TList * fLines
Definition: TMacro.h:36
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kFALSE
Definition: Rtypes.h:92
#define gInterpreter
Definition: TInterpreter.h:502
const char * Data() const
Definition: TString.h:349
Double_t dot(const TVector2 &v1, const TVector2 &v2)
Definition: CsgOps.cxx:333
void Class()
Definition: Class.C:29
This code implements the MD5 message-digest algorithm.
Definition: TMD5.h:46
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:33
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:918
char * out
Definition: TBase64.cxx:29
A doubly linked list.
Definition: TList.h:47
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:41
virtual Bool_t Load() const
Load the macro into the interpreter.
Definition: TMacro.cxx:245
TNamed & operator=(const TNamed &rhs)
TNamed assignment operator.
Definition: TNamed.cxx:40
TString GetString() const
Definition: TObjString.h:50
void Update(const UChar_t *buf, UInt_t len)
Update TMD5 object to reflect the concatenation of another buffer full of bytes.
Definition: TMD5.cxx:106
TMacro & operator=(const TMacro &)
Copy constructor.
Definition: TMacro.cxx:117
virtual Int_t GetValue(const char *name, Int_t dflt)
Returns the integer value for a resource.
Definition: TEnv.cxx:494
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:187
TList * GetListOfLines() const
Definition: TMacro.h:53
char * Form(const char *fmt,...)
void SaveSource(FILE *fp)
Save macro source in file pointer fp.
Definition: TMacro.cxx:379
virtual Int_t ReadFile(const char *filename)
Read lines in filename in this macro.
Definition: TMacro.cxx:334
TLine * l
Definition: textangle.C:4
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
Bool_t IsNull() const
Definition: TString.h:387
TString fName
Definition: TNamed.h:36
#define Printf
Definition: TGeoToOCC.h:18
long Long_t
Definition: RtypesCore.h:50
virtual Int_t GetSize() const
Definition: TCollection.h:95
TText * text
R__EXTERN TEnv * gEnv
Definition: TEnv.h:174
ClassImp(TMCParticle) void TMCParticle printf(": p=(%7.3f,%7.3f,%9.3f) ;", fPx, fPy, fPz)
unsigned long ULong_t
Definition: RtypesCore.h:51
virtual TMD5 * Checksum()
Returns checksum of the current content.
Definition: TMacro.cxx:192
TCanvas * slash()
Definition: slash.C:1
#define name(a, b)
Definition: linkTestLib0.cpp:5
virtual void Add(TObject *obj)
Definition: TList.h:81
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:567
virtual void Browse(TBrowser *b)
When clicking in the browser, the following action is performed on this macro, depending the content ...
Definition: TMacro.cxx:170
TString fParams
Definition: TMacro.h:37
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save macro source on stream out.
Definition: TMacro.cxx:393
unsigned char UChar_t
Definition: RtypesCore.h:34
const Bool_t kTRUE
Definition: Rtypes.h:91
virtual void SetParams(const char *params=0)
Set default parameters to execute this macro.
Definition: TMacro.cxx:417
TObject * obj
virtual TObjString * AddLine(const char *text)
Add line with text in the list of lines of this macro.
Definition: TMacro.cxx:137
virtual ~TMacro()
Delete this macro.
Definition: TMacro.cxx:108
virtual TObjString * GetLineWith(const char *text) const
Search the first line containing text.
Definition: TMacro.cxx:299