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;
28
29static ROOT::R::TRInterface *gR = nullptr;
31
32TRInterface::TRInterface(const Int_t argc, const Char_t *argv[], const Bool_t loadRcpp, const Bool_t verbose,
33 const Bool_t interactive)
34 : TObject()
35{
36 if (RInside::instancePtr()) throw std::runtime_error("Can only have one TRInterface instance");
37 fR = new RInside(argc, argv, loadRcpp, verbose, interactive);
38
39 //Installing the readline callbacks for completion in the
40 //method Interactive
42 RComp_assignBufferSym = Rf_install(".assignLinebuffer");
43 RComp_assignStartSym = Rf_install(".assignStart");
44 RComp_assignEndSym = Rf_install(".assignEnd");
45 RComp_assignTokenSym = Rf_install(".assignToken");
46 RComp_completeTokenSym = Rf_install(".completeToken");
47 RComp_getFileCompSym = Rf_install(".getFileComp");
48 RComp_retrieveCompsSym = Rf_install(".retrieveCompletions");
51 std::string osname = Eval("Sys.info()['sysname']");
52 //only for linux/mac windows is not supported by ROOT yet.
53#if defined(HAS_X11)
54 if (!gROOT->IsBatch()) {
55 if (gEnv->GetValue("X11.XInitThread", 1)) {
56 // Must be very first call before any X11 call !!
57 if (!XInitThreads())
58 Warning("OpenDisplay", "system has no X11 thread support");
59 }
60 }
61#endif
62 if (osname == "Linux") {
63 Execute("options(device='x11')");
64 } else {
65 Execute("options(device='quartz')");
66 }
67
68}
69
71{
73 if (th) delete th;
74 if (fR) delete fR;
75 if (gR == this) gR = nullptr;
76}
77
78//______________________________________________________________________________
80{
81 SEXP fans;
82
83 Int_t rc = kFALSE;
84 try {
85 rc = fR->parseEval(code.Data(), fans);
86 } catch (Rcpp::exception &__ex__) {
87 Error("Eval", "%s", __ex__.what());
89 } catch (...) {
90 Error("Eval", "Can execute the requested code: %s", code.Data());
91 }
92 ans = fans;
93 ans.SetStatus((rc == 0) ? kTRUE : kFALSE);
94 return rc;
95}
96
97//______________________________________________________________________________
99{
100 try {
101
102 fR->parseEvalQ(code.Data());
103 } catch (Rcpp::exception &__ex__) {
104 Error("Execute", "%s", __ex__.what());
106 } catch (...) {
107 Error("Execute", "Can execute the requested code: %s", code.Data());
108 }
109}
110
111//______________________________________________________________________________
113{
114// Execute R code.
115//The RObject result of execution is returned in TRObject
116
117 SEXP ans;
118
119 int rc = kFALSE;
120 try {
121 rc = fR->parseEval(code.Data(), ans);
122 } catch (Rcpp::exception &__ex__) {
123 Error("Eval", "%s", __ex__.what());
125 } catch (...) {
126 Error("Eval", "Can execute the requested code: %s", code.Data());
127 }
128
129 return TRObject(ans, (rc == 0) ? kTRUE : kFALSE);
130}
131
132
134{
135 //verbose mode shows you all the procedures in stdout/stderr
136 //very important to debug and to see the results.
137 fR->setVerbose(status);
138}
139
140//______________________________________________________________________________
145
146//______________________________________________________________________________
148{
149 fR->assign(*obj.f, name.Data());
150}
151
152//______________________________________________________________________________
154{
155 //This method lets you pass c++ functions to R environment.
156 fR->assign(obj.df, name.Data());
157}
158
159//______________________________________________________________________________
161{
162 while (kTRUE) {
163 Char_t *line = readline("[r]:");
164 if (!line) continue;
165 if (std::string(line) == ".q") break;
166 Execute(line);
167 if (*line) add_history(line);
168 free(line);
169 }
170}
171
172
173//______________________________________________________________________________
175{
176 if (!gR) {
177 const Char_t *R_argv[] = {"rootr", "--gui=none", "--no-save", "--no-readline",
178 "--silent", "--vanilla", "--slave"};
179 gR = new TRInterface(7, R_argv, true, false, false);
180 }
181 gR->ProcessEventsLoop();
182 return gR;
183}
184
185//______________________________________________________________________________
190
191namespace {
192
193// Per CRAN policy, an R package name starts with a letter, contains only ASCII
194// letters, digits, and dots, and does not end with a dot. Restricting to this
195// set is a helpful validation step for the user and prevents R-source
196// injection via the string concatenation done in IsInstalled / Require /
197// Install below.
199{
200 const Ssiz_t n = pkg.Length();
201 if (n == 0)
202 return false;
203 const char first = pkg[0];
204 if (!((first >= 'A' && first <= 'Z') || (first >= 'a' && first <= 'z')))
205 return false;
206 for (Ssiz_t i = 1; i < n; ++i) {
207 const char c = pkg[i];
208 const Bool_t ok = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '.';
209 if (!ok)
210 return false;
211 }
212 return pkg[n - 1] != '.';
213}
214
215// Allow only an http(s)/ftp/file URL with no characters that could break
216// out of the R single-quoted literal in Install().
217bool IsValidRReposUrl(const TString &repos)
218{
219 const Ssiz_t n = repos.Length();
220 if (n == 0)
221 return false;
222 const char *prefixes[] = {"http://", "https://", "ftp://", "file://"};
223 Bool_t prefixOk = false;
224 for (const char *s : prefixes) {
225 if (repos.BeginsWith(s)) {
226 prefixOk = true;
227 break;
228 }
229 }
230 if (!prefixOk)
231 return false;
232 for (Ssiz_t i = 0; i < n; ++i) {
233 const char c = repos[i];
234 if (c == '\'' || c == '\\' || c == '`' || c == ';' || c == '\n' || c == '\r')
235 return false;
236 }
237 return true;
238}
239
240} // namespace
241
242//______________________________________________________________________________
244{
245 if (!IsValidRPackageName(pkg)) {
246 Error("IsInstalled", "Invalid R package name: %s", pkg.Data());
247 return kFALSE;
248 }
249 TString cmd = "is.element('" + pkg + "', installed.packages()[,1])";
250 return this->Eval(cmd).As<Bool_t>();
251}
252
253//______________________________________________________________________________
255{
256 if (!IsValidRPackageName(pkg)) {
257 Error("Require", "Invalid R package name: %s", pkg.Data());
258 return kFALSE;
259 }
260 TString cmd = "require('" + pkg + "',quiet=TRUE)";
261 return this->Eval(cmd).As<Bool_t>();
262}
263
264//______________________________________________________________________________
266{
267 if (!IsValidRPackageName(pkg)) {
268 Error("Install", "Invalid R package name: %s", pkg.Data());
269 return kFALSE;
270 }
271 if (!IsValidRReposUrl(repos)) {
272 Error("Install", "Invalid R repository URL: %s", repos.Data());
273 return kFALSE;
274 }
275 TString cmd = "install.packages('" + pkg + "',repos='" + repos + "',dependencies=TRUE)";
276 this->Eval(cmd);
277 return IsInstalled(pkg);
278}
279
280
281#undef _POSIX_C_SOURCE
282#include <R_ext/eventloop.h>
283
284//______________________________________________________________________________
286{
287 if (!statusEventLoop) {
288 th = new TThread([](void */*args */) {
289 while (statusEventLoop) {
290 fd_set *fd;
291 Int_t usec = 10000;
292 fd = R_checkActivity(usec, 0);
294 if (gSystem) gSystem->Sleep(100);
295 }
296 });
298 th->Run();
299 }
300}
void Binding()
Definition Binding.C:21
#define c(i)
Definition RSha256.hxx:101
bool Bool_t
Boolean (0=false, 1=true) (bool)
Definition RtypesCore.h:77
char Char_t
Character 1 byte (char)
Definition RtypesCore.h:51
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
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:145
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:426
R__EXTERN TSystem * gSystem
Definition TSystem.h:582
#define free
Definition civetweb.c:1578
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:503
Mother of all ROOT objects.
Definition TObject.h:42
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1081
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1095
Basic string class.
Definition TString.h:138
const char * Data() const
Definition TString.h:384
virtual void Sleep(UInt_t milliSec)
Sleep milliSec milli seconds.
Definition TSystem.cxx:439
<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:569
TLine * line
const Int_t n
Definition legend1.C:16
namespace associated R package for ROOT.
Definition RExports.h:72
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