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