Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TRInterface.cxx
Go to the documentation of this file.
1// Author: Omar Zapata Omar.Zapata@cern.ch 2014
2
3/*************************************************************************
4 * Copyright (C) 1995-2021, Rene Brun and Fons Rademakers. *
5 * All rights reserved. *
6 * *
7 * For the licensing terms see $ROOTSYS/LICENSE. *
8 * For the list of contributors see $ROOTSYS/README/CREDITS. *
9 *************************************************************************/
10#include<TRInterface.h>
11#include"TRCompletion.h"
12#include<vector>
13
14extern "C"
15{
16#include <stdio.h>
17#include <stdlib.h>
18}
19#include <TRint.h>
20#include <TSystem.h>
21
22#if defined(HAS_X11)
23#include <X11/Xlib.h>
24#include "TROOT.h"
25#include "TEnv.h"
26#endif
27using namespace ROOT::R;
29
30static ROOT::R::TRInterface *gR = nullptr;
32
33TRInterface::TRInterface(const Int_t argc, const Char_t *argv[], const Bool_t loadRcpp, const Bool_t verbose,
34 const Bool_t interactive)
35 : TObject()
36{
37 if (RInside::instancePtr()) throw std::runtime_error("Can only have one TRInterface instance");
38 fR = new RInside(argc, argv, loadRcpp, verbose, interactive);
39
40 //Installing the readline callbacks for completion in the
41 //method Interactive
43 RComp_assignBufferSym = Rf_install(".assignLinebuffer");
44 RComp_assignStartSym = Rf_install(".assignStart");
45 RComp_assignEndSym = Rf_install(".assignEnd");
46 RComp_assignTokenSym = Rf_install(".assignToken");
47 RComp_completeTokenSym = Rf_install(".completeToken");
48 RComp_getFileCompSym = Rf_install(".getFileComp");
49 RComp_retrieveCompsSym = Rf_install(".retrieveCompletions");
52 std::string osname = Eval("Sys.info()['sysname']");
53 //only for linux/mac windows is not supported by ROOT yet.
54#if defined(HAS_X11)
55 if (!gROOT->IsBatch()) {
56 if (gEnv->GetValue("X11.XInitThread", 1)) {
57 // Must be very first call before any X11 call !!
58 if (!XInitThreads())
59 Warning("OpenDisplay", "system has no X11 thread support");
60 }
61 }
62#endif
63 if (osname == "Linux") {
64 Execute("options(device='x11')");
65 } else {
66 Execute("options(device='quartz')");
67 }
68
69}
70
72{
74 if (th) delete th;
75 if (fR) delete fR;
76 if (gR == this) gR = nullptr;
77}
78
79//______________________________________________________________________________
81{
82 SEXP fans;
83
84 Int_t rc = kFALSE;
85 try {
86 rc = fR->parseEval(code.Data(), fans);
87 } catch (Rcpp::exception &__ex__) {
88 Error("Eval", "%s", __ex__.what());
90 } catch (...) {
91 Error("Eval", "Can execute the requested code: %s", code.Data());
92 }
93 ans = fans;
94 ans.SetStatus((rc == 0) ? kTRUE : kFALSE);
95 return rc;
96}
97
98//______________________________________________________________________________
100{
101 try {
102
103 fR->parseEvalQ(code.Data());
104 } catch (Rcpp::exception &__ex__) {
105 Error("Execute", "%s", __ex__.what());
107 } catch (...) {
108 Error("Execute", "Can execute the requested code: %s", code.Data());
109 }
110}
111
112//______________________________________________________________________________
114{
115// Execute R code.
116//The RObject result of execution is returned in TRObject
117
118 SEXP ans;
119
120 int rc = kFALSE;
121 try {
122 rc = fR->parseEval(code.Data(), ans);
123 } catch (Rcpp::exception &__ex__) {
124 Error("Eval", "%s", __ex__.what());
126 } catch (...) {
127 Error("Eval", "Can execute the requested code: %s", code.Data());
128 }
129
130 return TRObject(ans, (rc == 0) ? kTRUE : kFALSE);
131}
132
133
135{
136 //verbose mode shows you all the procedures in stdout/stderr
137 //very important to debug and to see the results.
138 fR->setVerbose(status);
139}
140
141//______________________________________________________________________________
146
147//______________________________________________________________________________
149{
150 fR->assign(*obj.f, name.Data());
151}
152
153//______________________________________________________________________________
155{
156 //This method lets you pass c++ functions to R environment.
157 fR->assign(obj.df, name.Data());
158}
159
160//______________________________________________________________________________
162{
163 while (kTRUE) {
164 Char_t *line = readline("[r]:");
165 if (!line) continue;
166 if (std::string(line) == ".q") break;
167 Execute(line);
168 if (*line) add_history(line);
169 free(line);
170 }
171}
172
173
174//______________________________________________________________________________
176{
177 if (!gR) {
178 const Char_t *R_argv[] = {"rootr", "--gui=none", "--no-save", "--no-readline",
179 "--silent", "--vanilla", "--slave"};
180 gR = new TRInterface(7, R_argv, true, false, false);
181 }
182 gR->ProcessEventsLoop();
183 return gR;
184}
185
186//______________________________________________________________________________
191
192namespace {
193
194// Per CRAN policy, an R package name starts with a letter, contains only ASCII
195// letters, digits, and dots, and does not end with a dot. Restricting to this
196// set is a helpful validation step for the user and prevents R-source
197// injection via the string concatenation done in IsInstalled / Require /
198// Install below.
200{
201 const Ssiz_t n = pkg.Length();
202 if (n == 0)
203 return false;
204 const char first = pkg[0];
205 if (!((first >= 'A' && first <= 'Z') || (first >= 'a' && first <= 'z')))
206 return false;
207 for (Ssiz_t i = 1; i < n; ++i) {
208 const char c = pkg[i];
209 const Bool_t ok = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '.';
210 if (!ok)
211 return false;
212 }
213 return pkg[n - 1] != '.';
214}
215
216// Allow only an http(s)/ftp/file URL with no characters that could break
217// out of the R single-quoted literal in Install().
218bool IsValidRReposUrl(const TString &repos)
219{
220 const Ssiz_t n = repos.Length();
221 if (n == 0)
222 return false;
223 const char *prefixes[] = {"http://", "https://", "ftp://", "file://"};
224 Bool_t prefixOk = false;
225 for (const char *s : prefixes) {
226 if (repos.BeginsWith(s)) {
227 prefixOk = true;
228 break;
229 }
230 }
231 if (!prefixOk)
232 return false;
233 for (Ssiz_t i = 0; i < n; ++i) {
234 const char c = repos[i];
235 if (c == '\'' || c == '\\' || c == '`' || c == ';' || c == '\n' || c == '\r')
236 return false;
237 }
238 return true;
239}
240
241} // namespace
242
243//______________________________________________________________________________
245{
246 if (!IsValidRPackageName(pkg)) {
247 Error("IsInstalled", "Invalid R package name: %s", pkg.Data());
248 return kFALSE;
249 }
250 TString cmd = "is.element('" + pkg + "', installed.packages()[,1])";
251 return this->Eval(cmd).As<Bool_t>();
252}
253
254//______________________________________________________________________________
256{
257 if (!IsValidRPackageName(pkg)) {
258 Error("Require", "Invalid R package name: %s", pkg.Data());
259 return kFALSE;
260 }
261 TString cmd = "require('" + pkg + "',quiet=TRUE)";
262 return this->Eval(cmd).As<Bool_t>();
263}
264
265//______________________________________________________________________________
267{
268 if (!IsValidRPackageName(pkg)) {
269 Error("Install", "Invalid R package name: %s", pkg.Data());
270 return kFALSE;
271 }
272 if (!IsValidRReposUrl(repos)) {
273 Error("Install", "Invalid R repository URL: %s", repos.Data());
274 return kFALSE;
275 }
276 TString cmd = "install.packages('" + pkg + "',repos='" + repos + "',dependencies=TRUE)";
277 this->Eval(cmd);
278 return IsInstalled(pkg);
279}
280
281
282#undef _POSIX_C_SOURCE
283#include <R_ext/eventloop.h>
284
285//______________________________________________________________________________
287{
288 if (!statusEventLoop) {
289 th = new TThread([](void */*args */) {
290 while (statusEventLoop) {
291 fd_set *fd;
292 Int_t usec = 10000;
293 fd = R_checkActivity(usec, 0);
295 if (gSystem) gSystem->Sleep(100);
296 }
297 });
299 th->Run();
300 }
301}
void Binding()
Definition Binding.C:21
#define c(i)
Definition RSha256.hxx:101
bool Bool_t
Definition RtypesCore.h:63
char Char_t
Definition RtypesCore.h:37
constexpr Bool_t kFALSE
Definition RtypesCore.h:101
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
#define ClassImp(name)
Definition Rtypes.h:377
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
char name[80]
Definition TGX11.cxx:110
void add_history()
rl_completion_func_t * rl_attempted_completion_function
char * readline()
static Bool_t statusEventLoop
static ROOT::R::TRInterface * gR
#define gROOT
Definition TROOT.h:414
R__EXTERN TSystem * gSystem
Definition TSystem.h:566
#define free
Definition civetweb.c:1539
This is a class to create DataFrames from ROOT to R.
Rcpp::DataFrame df
This is a class to pass functions from ROOT to R.
ROOT R was implemented using the R Project library and the modules Rcpp and RInside
TRInterface(const Int_t argc=0, const Char_t *argv[]=NULL, const Bool_t loadRcpp=true, const Bool_t verbose=false, const Bool_t interactive=true)
The command line arguments are by default argc=0 and argv=NULL, The verbose mode is by default disabl...
void Execute(const TString &code)
Method to eval R code.
static TRInterface & Instance()
static method to get an TRInterface instance reference
void SetVerbose(Bool_t status)
Method to set verbose mode, that produce extra output.
Bool_t IsInstalled(TString pkg)
Method to verify if a package is installed.
Bool_t Require(TString pkg)
Method to load an R's package.
Int_t Eval(const TString &code, TRObject &ans)
Method to eval R code and you get the result in a reference to TRObject.
void Interactive()
Method to get a R prompt to work interactively with tab completion support.
void ProcessEventsLoop()
Init event loop in a thread to support actions in windows from R graphics system.
Binding operator[](const TString &name)
void Assign(const T &var, const TString &name)
Template method to assign C++ variables into R environment.
static TRInterface * InstancePtr()
static method to get an TRInterface instance pointer
Bool_t Install(TString pkg, TString repos="http://cran.r-project.org")
Method to install an R's package.
This is a class to get ROOT's objects from R's objects.
Definition TRObject.h:70
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:491
Mother of all ROOT objects.
Definition TObject.h:41
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:973
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:987
Basic string class.
Definition TString.h:139
const char * Data() const
Definition TString.h:376
virtual void Sleep(UInt_t milliSec)
Sleep milliSec milli seconds.
Definition TSystem.cxx:437
<div class="legacybox"><h2>Legacy Code</h2> TThread is a legacy interface: there will be no bug fixes...
Definition TThread.h:40
Int_t Run(void *arg=nullptr, const int affinity=-1)
Start the thread.
Definition TThread.cxx:566
TLine * line
const Int_t n
Definition legend1.C:16
namespace associated R package for ROOT.
Definition RExports.h:71
SEXP RComp_assignBufferSym
SEXP RComp_completeTokenSym
SEXP RComp_retrieveCompsSym
SEXP rcompgen_rho
SEXP RComp_assignStartSym
SEXP RComp_assignTokenSym
SEXP RComp_getFileCompSym
char ** R_custom_completion(const char *text, int start, int end)
SEXP RComp_assignEndSym