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
15Class supporting a collection of lines with C++ code.
16A TMacro can be executed, saved to a ROOT file, edited, etc.
17
18A macro can be built line by line by calling the AddLine function.
19or it can be created directly from a file via the special constructor
20when the first argument is a file name.
21
22A macro can be executed via the Exec function.
23Arguments can be specified when calling Exec.
24
25A macro can be drawn in a pad. When the pad is updated, the macro is
26automatically executed.
27
28The code in the macro can be saved via the SaveSource function.
29If the macro is in the list of primitives of a pad/canvas, the macro
30will be saved in the script generated by TCanvas::SaveSource.
31
32A macro can be written to a ROOT file via TObject::Write.
33
34Examples:
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
64TMacro::TMacro(): TNamed(), fLines(nullptr)
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
75TMacro::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;
91 }
92 delete [] s;
93}
94
95////////////////////////////////////////////////////////////////////////////////
96/// Copy constructor.
97
98TMacro::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%zx)",opt.Data(),(size_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 *)nullptr;
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
268Longptr_t TMacro::Exec(const char *params, Int_t* error)
269{
270 if ( !gROOT->GetGlobalFunction(GetName(), nullptr, 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(), nullptr, 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 Longptr_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 nullptr;
306 TIter next(fLines);
307 TObjString *obj;
308 while ((obj = (TObjString*) next())) {
309 if (strstr(obj->GetName(),text)) return obj;
310 }
311 return nullptr;
312}
313
314////////////////////////////////////////////////////////////////////////////////
315/// Execute this macro (called by TPad::Paint).
316
318{
319 Exec(option);
320}
321
322////////////////////////////////////////////////////////////////////////////////
323/// Print contents of this macro.
324
325void 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
338Int_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
363void 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
383void 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
397void 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
421void TMacro::SetParams(const char *params)
422{
423 if (params) fParams = params;
424}
void Class()
Definition: Class.C:29
int Int_t
Definition: RtypesCore.h:45
long Longptr_t
Definition: RtypesCore.h:82
unsigned char UChar_t
Definition: RtypesCore.h:38
const Bool_t kFALSE
Definition: RtypesCore.h:101
bool Bool_t
Definition: RtypesCore.h:63
long long Long64_t
Definition: RtypesCore.h:80
const Bool_t kTRUE
Definition: RtypesCore.h:100
const char Option_t
Definition: RtypesCore.h:66
#define ClassImp(name)
Definition: Rtypes.h:364
R__EXTERN TEnv * gEnv
Definition: TEnv.h:170
char name[80]
Definition: TGX11.cxx:110
#define gInterpreter
Definition: TInterpreter.h:562
#define gROOT
Definition: TROOT.h:404
char * Form(const char *fmt,...)
void Printf(const char *fmt,...)
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:37
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:184
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition: TEnv.cxx:491
A doubly linked list.
Definition: TList.h:44
virtual void Add(TObject *obj)
Definition: TList.h:87
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:470
This code implements the MD5 message-digest algorithm.
Definition: TMD5.h:44
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
void Final()
MD5 finalization, ends an MD5 message-digest operation, writing the the message digest and zeroizing ...
Definition: TMD5.cxx:167
Class supporting a collection of lines with C++ code.
Definition: TMacro.h:31
virtual Longptr_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
virtual TMD5 * Checksum()
Returns checksum of the current content.
Definition: TMacro.cxx:196
TString fParams
Definition: TMacro.h:35
TList * fLines
Definition: TMacro.h:34
virtual Bool_t Load() const
Load the macro into the interpreter.
Definition: TMacro.cxx:249
virtual ~TMacro()
Delete this macro.
Definition: TMacro.cxx:112
virtual void Paint(Option_t *option="")
Execute this macro (called by TPad::Paint).
Definition: TMacro.cxx:317
virtual TObjString * AddLine(const char *text)
Add line with text in the list of lines of this macro.
Definition: TMacro.cxx:141
virtual Int_t ReadFile(const char *filename)
Read lines in filename in this macro.
Definition: TMacro.cxx:338
void SaveSource(FILE *fp)
Save macro source in file pointer fp.
Definition: TMacro.cxx:383
TMacro()
Create an empty macro, use AddLine() or ReadFile() to fill this macro.
Definition: TMacro.cxx:64
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save macro source on stream out.
Definition: TMacro.cxx:397
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
TMacro & operator=(const TMacro &)
Copy constructor.
Definition: TMacro.cxx:121
virtual void SetParams(const char *params=0)
Set default parameters to execute this macro.
Definition: TMacro.cxx:421
TList * GetListOfLines() const
Definition: TMacro.h:51
virtual TObjString * GetLineWith(const char *text) const
Search the first line containing text.
Definition: TMacro.cxx:303
virtual void Print(Option_t *option="") const
Print contents of this macro.
Definition: TMacro.cxx:325
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
TString fTitle
Definition: TNamed.h:33
TString fName
Definition: TNamed.h:32
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
TNamed & operator=(const TNamed &rhs)
TNamed assignment operator.
Definition: TNamed.cxx:51
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
Collectable string class.
Definition: TObjString.h:28
const char * GetName() const
Returns name of object.
Definition: TObjString.h:38
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:130
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:893
Basic string class.
Definition: TString.h:136
Ssiz_t Length() const
Definition: TString.h:410
const char * Data() const
Definition: TString.h:369
Bool_t IsNull() const
Definition: TString.h:407
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:624
TText * text
TLine * line
static constexpr double s
TCanvas * slash()
Definition: slash.C:1
auto * l
Definition: textangle.C:4