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