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