Logo ROOT  
Reference Guide
Loading...
Searching...
No Matches
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
59
60////////////////////////////////////////////////////////////////////////////////
61/// Create an empty macro, use AddLine() or ReadFile() to fill this macro.
62
64{
65}
66
67////////////////////////////////////////////////////////////////////////////////
68/// Create a macro with a name and a title.
69/// If name contains a '.' it is assumed to be the name of a file, and
70/// - the macro is automatically filled by reading all the lines in the file,
71/// - if the title is empty, it will be set to the name of the file,
72/// - the name will be set to the filename without path or extension.
73
74TMacro::TMacro(const char *name, const char *title): TNamed(name,title)
75{
76 fLines = new TList();
77 if (!name) return;
78 Int_t nch = strlen(name);
79 char *s = new char[nch+1];
80 strlcpy(s,name,nch+1);
81 char *slash = (char*)strrchr(s,'/');
82 if (!slash) slash = s;
83 else ++slash;
84 char *dot = (char*)strchr(slash,'.');
85 if (dot) {
86 *dot = 0;
87 fName = slash;
88 if (fTitle.Length() == 0) fTitle = name;
90 }
91 delete [] s;
92}
93
94////////////////////////////////////////////////////////////////////////////////
95/// Copy constructor.
96
97TMacro::TMacro(const TMacro &macro): TNamed(macro)
98{
99 fLines = new TList();
100 TIter next(macro.GetListOfLines());
101 while (auto obj = 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 while (auto obj = next())
128 fLines->Add(new TObjString(obj->GetName()));
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 gROOT->ProcessLine(TString::Format(".x %s((TMacro*)0x%zx)", opt.Data(), (size_t)this).Data());
183 return;
184 }
185}
186
187////////////////////////////////////////////////////////////////////////////////
188/// Returns checksum of the current content. The returned TMD5 object must
189/// be deleted by the user. Returns 0 in case of error.
190
192{
193 if (!fLines || fLines->GetSize() <= 0)
194 return (TMD5 *)nullptr;
195
196 TMD5 *md5 = new TMD5;
197
198 // Fill (same params as in TMD5::FileChecksum)
199 const Int_t bufSize = 8192;
200 UChar_t buf[bufSize];
201 Long64_t pos = 0;
202 Long64_t left = bufSize;
203
204 TIter nxl(fLines);
205 while (auto l = (TObjString *) nxl()) {
206 TString line = l->GetString();
207 line += '\n';
208 Int_t len = line.Length();
209 const char *p = line.Data();
210 if (left > len) {
211 strlcpy((char *)&buf[pos], p, len+1);
212 pos += len;
213 left -= len;
214 } else if (left == len) {
215 strlcpy((char *)&buf[pos], p, len+1);
216 md5->Update(buf, bufSize);
217 pos = 0;
218 left = bufSize;
219 } else {
220 strlcpy((char *)&buf[pos], p, left+1);
221 md5->Update(buf, bufSize);
222 len -= left;
223 p += left;
224 pos = 0;
225 left = bufSize;
226 strlcpy((char *)&buf[pos], p, len+1);
227 pos += len;
228 left -= len;
229 }
230 }
231 md5->Update(buf, pos);
232
233 // Finalize
234 md5->Final();
235
236 return md5;
237}
238
239////////////////////////////////////////////////////////////////////////////////
240/// Load the macro into the interpreter.
241/// Return true in case the loading was successful.
242
244{
245 std::stringstream ss;
246
247 TIter next(fLines);
248 while (auto obj = (TObjString*) next())
249 ss << obj->GetName() << std::endl;
250
251 return gInterpreter->LoadText(ss.str().c_str());
252}
253
254////////////////////////////////////////////////////////////////////////////////
255/// Execute this macro with params, if params is 0, default parameters
256/// (set via SetParams) are used.
257/// error is set to an TInterpreter::EErrorCode by TApplication::ProcessLine().
258/// Returns the result of the macro (return value or value of the last
259/// expression), cast to a Long_t.
260
261Longptr_t TMacro::Exec(const char *params, Int_t* error)
262{
263 if ( !gROOT->GetGlobalFunction(GetName(), nullptr, kTRUE) ) {
264 if (!Load()) {
265 if (error) *error = 1;
266 return 0;
267 }
268 }
269
270 // if macro has been executed, look for global function with name
271 // of macro and re-execute this global function, if not found then
272 // macro is unnamed macro, which we re-execute from file
273 if ( gROOT->GetGlobalFunction(GetName(), nullptr, kTRUE) ) {
274 gROOT->SetExecutingMacro(kTRUE);
275 TString exec = GetName();
276 TString p = params;
277 if (p == "") p = fParams;
278 if (p != "")
279 exec += "(" + p + ")";
280 else
281 exec += "()";
282 Longptr_t ret = gROOT->ProcessLine(exec, error);
283 //enable gROOT->Reset
284 gROOT->SetExecutingMacro(kFALSE);
285 return ret;
286 }
287
288 Error("Exec","Macro does not contains function named %s.",GetName());
289 if (error) *error = 1;
290 return 0;
291}
292
293////////////////////////////////////////////////////////////////////////////////
294/// Search the first line containing text.
295
297{
298 if (!fLines) return nullptr;
299 TIter next(fLines);
300 while (auto obj = (TObjString*) next()) {
301 if (strstr(obj->GetName(),text))
302 return obj;
303 }
304 return nullptr;
305}
306
307////////////////////////////////////////////////////////////////////////////////
308/// Execute this macro (called by TPad::Paint).
309
311{
312 Exec(option);
313}
314
315////////////////////////////////////////////////////////////////////////////////
316/// Print contents of this macro.
317
318void TMacro::Print(Option_t * /*option*/) const
319{
320 TIter next(fLines);
321 while (auto obj = next())
322 printf("%s\n", obj->GetName());
323}
324
325////////////////////////////////////////////////////////////////////////////////
326/// Read lines in filename in this macro.
327
328Int_t TMacro::ReadFile(const char *filename)
329{
330 if (!fLines) fLines = new TList();
331 std::ifstream in;
332 in.open(filename);
333 if (!in.good()) {
334 Error("ReadFile","Cannot open file: %s",filename);
335 return 0;
336 }
337 char *line = new char[10000];
338 Int_t nlines = 0;
339 while (1) {
340 in.getline(line,10000);
341 if (!in.good()) break;
342 if (in.eof()) break;
343 fLines->Add(new TObjString(line));
344 nlines++;
345 }
346 delete [] line;
347 return nlines;
348}
349
350////////////////////////////////////////////////////////////////////////////////
351/// Save macro source in filename.
352
353void TMacro::SaveSource(const char *filename)
354{
355 std::ofstream out;
356 out.open(filename, std::ios::out);
357 if (!out.good()) {
358 Error("SaveSource", "cannot open file: %s",filename);
359 return;
360 }
361 TIter next(fLines);
362 while (auto obj = next())
363 out << obj->GetName() << std::endl;
364 out.close();
365}
366
367////////////////////////////////////////////////////////////////////////////////
368/// Save macro source in file pointer fp.
369
370void TMacro::SaveSource(FILE *fp)
371{
372 TIter next(fLines);
373 while (auto obj = next())
374 fprintf(fp, "%s\n", obj->GetName());
375 fclose(fp);
376}
377
378////////////////////////////////////////////////////////////////////////////////
379/// Save macro source on stream out.
380
381void TMacro::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
382{
384 out, Class(), "macro",
385 TString::Format("\"%s\", \"%s\"", GetName(), TString(GetTitle()).ReplaceSpecialCppChars().Data()));
386
387 TIter next(fLines);
388 while (auto obj = next()) {
389 TString s = obj->GetName();
390 out << " macro->AddLine(\"" << s.ReplaceSpecialCppChars() << "\");\n";
391 }
392 out << " macro->Draw(\"" << TString(option).ReplaceSpecialCppChars() << "\");\n";
393}
394
395////////////////////////////////////////////////////////////////////////////////
396/// Set default parameters to execute this macro.
397
398void TMacro::SetParams(const char *params)
399{
400 if (params) fParams = params;
401}
char * ret
Definition Rotated.cxx:221
int Int_t
Signed integer 4 bytes (int).
Definition RtypesCore.h:59
long Longptr_t
Integer large enough to hold a pointer (platform-dependent).
Definition RtypesCore.h:89
unsigned char UChar_t
Unsigned Character 1 byte (unsigned char).
Definition RtypesCore.h:52
bool Bool_t
Boolean (0=false, 1=true) (bool).
Definition RtypesCore.h:77
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
long long Long64_t
Portable signed long integer 8 bytes.
Definition RtypesCore.h:83
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
const char Option_t
Option string (const char).
Definition RtypesCore.h:80
externTEnv * gEnv
Definition TEnv.h:170
char name[80]
Definition TGX11.cxx:148
#define gInterpreter
#define gROOT
Definition TROOT.h:417
Using a TBrowser one can browse all ROOT objects.
Definition TBrowser.h:37
A doubly linked list.
Definition TList.h:38
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:107
void Final()
MD5 finalization, ends an MD5 message-digest operation, writing the the message digest and zeroizing ...
Definition TMD5.cxx:166
virtual TMD5 * Checksum()
Returns checksum of the current content.
Definition TMacro.cxx:191
TString fParams
Definition TMacro.h:35
TList * fLines
Definition TMacro.h:34
void Print(Option_t *option="") const override
Print contents of this macro.
Definition TMacro.cxx:318
virtual Bool_t Load() const
Load the macro into the interpreter.
Definition TMacro.cxx:243
virtual ~TMacro()
Delete this macro.
Definition TMacro.cxx:110
virtual void SetParams(const char *params=nullptr)
Set default parameters to execute this macro.
Definition TMacro.cxx:398
void SavePrimitive(std::ostream &out, Option_t *option="") override
Save macro source on stream out.
Definition TMacro.cxx:381
virtual TObjString * AddLine(const char *text)
Add line with text in the list of lines of this macro.
Definition TMacro.cxx:137
virtual Int_t ReadFile(const char *filename)
Read lines in filename in this macro.
Definition TMacro.cxx:328
void SaveSource(FILE *fp)
Save macro source in file pointer fp.
Definition TMacro.cxx:370
virtual Longptr_t Exec(const char *params=nullptr, Int_t *error=nullptr)
Execute this macro with params, if params is 0, default parameters (set via SetParams) are used.
Definition TMacro.cxx:261
TMacro()
Create an empty macro, use AddLine() or ReadFile() to fill this macro.
Definition TMacro.cxx:63
static TClass * Class()
TMacro & operator=(const TMacro &)
Copy constructor.
Definition TMacro.cxx:119
TList * GetListOfLines() const
Definition TMacro.h:51
void Paint(Option_t *option="") override
Execute this macro (called by TPad::Paint).
Definition TMacro.cxx:310
void Browse(TBrowser *b) override
When clicking in the browser, the following action is performed on this macro, depending the content ...
Definition TMacro.cxx:170
virtual TObjString * GetLineWith(const char *text) const
Search the first line containing text.
Definition TMacro.cxx:296
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
TString fTitle
Definition TNamed.h:33
TNamed()
Definition TNamed.h:38
TString fName
Definition TNamed.h:32
TNamed & operator=(const TNamed &rhs)
TNamed assignment operator.
Definition TNamed.cxx:50
Collectable string class.
Definition TObjString.h:28
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1098
static void SavePrimitiveConstructor(std::ostream &out, TClass *cl, const char *variable_name, const char *constructor_agrs="", Bool_t empty_line=kTRUE)
Save object constructor in the output stream "out".
Definition TObject.cxx:777
Basic string class.
Definition TString.h:138
TString & ReplaceSpecialCppChars()
Find special characters which are typically used in printf() calls and replace them by appropriate es...
Definition TString.cxx:1121
const char * Data() const
Definition TString.h:384
Bool_t IsNull() const
Definition TString.h:422
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2385
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:641
TText * text
TLine * line
TCanvas * slash()
Definition slash.C:1
TLine l
Definition textangle.C:4