1 /*
2 * RSexp.cpp
3 *
4 * Copyright (C) 2021 by RStudio, PBC
5 *
6 * Unless you have received this program directly from RStudio pursuant
7 * to the terms of a commercial license agreement with RStudio, then
8 * this program is licensed to you under the terms of version 3 of the
9 * GNU Affero General Public License. This program is distributed WITHOUT
10 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
11 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
12 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
13 *
14 */
15
16 #define R_INTERNAL_FUNCTIONS
17 #define RSTUDIO_DEBUG_LABEL "rsexp"
18 // #define RSTUDIO_ENABLE_DEBUG_MACROS
19
20 #include <cctype>
21
22 #include <gsl/gsl>
23
24 #include <r/RInternal.hpp>
25 #include <r/RJson.hpp>
26 #include <r/RSexp.hpp>
27
28 #include <core/Algorithm.hpp>
29
30 #include <boost/function.hpp>
31 #include <boost/numeric/conversion/cast.hpp>
32 #include <boost/optional.hpp>
33 #include <boost/bind/bind.hpp>
34
35 #include <core/Macros.hpp>
36 #include <core/Log.hpp>
37 #include <core/DateTime.hpp>
38
39 #include <r/RExec.hpp>
40 #include <r/RErrorCategory.hpp>
41 #include <r/RUtil.hpp>
42
43 // clean out global definitions of TRUE and FALSE so we can
44 // use the Rboolean variations of them
45 #undef TRUE
46 #undef FALSE
47
48 using namespace rstudio::core;
49 using namespace boost::placeholders;
50
51 namespace rstudio {
52 namespace r {
53
54 using namespace exec;
55
56 namespace sexp {
57
58 using namespace core::r_util;
59
60 namespace {
61
62 struct LexicalComparator
63 {
operator ()rstudio::r::sexp::__anon436a24390111::LexicalComparator64 inline bool operator()(const char* lhs, const char* rhs) const
65 {
66 return strcmp(lhs, rhs) < 0;
67 }
68 };
69
70 // A simple wrapper set class that is primarily used as a means
71 // to re-use R's internal string cache, while providing lexical
72 // comparator for efficient lookup.
73 class StringSet : public std::set<const char*, LexicalComparator>
74 {
75 public:
contains(const char * value)76 bool contains(const char* value)
77 {
78 return this->find(value) != this->end();
79 }
80 };
81
82 struct FunctionSymbolUsage
83 {
84 StringSet symbolsUsed;
85 StringSet symbolsCheckedForMissingness;
86 };
87
88 // singleton: cache the result of 'examination' of functions
89 class FunctionSymbolUsageCache : boost::noncopyable
90 {
91 typedef std::pair<SEXP, SEXP> FunctionEnvironmentPair;
92
93 public:
94
contains(SEXP object)95 bool contains(SEXP object)
96 {
97 return database_.count(pair(object));
98 }
99
get(SEXP object)100 FunctionSymbolUsage& get(SEXP object)
101 {
102 return database_[pair(object)];
103 }
104
put(SEXP object,const FunctionSymbolUsage & usage)105 void put(SEXP object, const FunctionSymbolUsage& usage)
106 {
107 database_[pair(object)] = usage;
108 }
109
110 private:
111
pair(SEXP object)112 static FunctionEnvironmentPair pair(SEXP object)
113 {
114 return std::make_pair(object, CLOENV(object));
115 }
116
117 std::map<FunctionEnvironmentPair, FunctionSymbolUsage> database_;
118
119 };
120
functionSymbolUsageCache()121 FunctionSymbolUsageCache& functionSymbolUsageCache()
122 {
123 static FunctionSymbolUsageCache instance;
124 return instance;
125 }
126
translate(SEXP charSEXP,bool asUtf8=false)127 std::string translate(SEXP charSEXP, bool asUtf8 = false)
128 {
129 if (asUtf8)
130 {
131 if (Rf_getCharCE(charSEXP) == CE_UTF8)
132 return std::string(CHAR(charSEXP), LENGTH(charSEXP));
133 else
134 return Rf_translateCharUTF8(charSEXP);
135 }
136 else
137 {
138 if (Rf_getCharCE(charSEXP) == CE_NATIVE)
139 return std::string(CHAR(charSEXP), LENGTH(charSEXP));
140 else
141 return Rf_translateChar(charSEXP);
142 }
143 }
144
asStringImpl(SEXP objectSEXP,bool asUtf8)145 std::string asStringImpl(SEXP objectSEXP, bool asUtf8)
146 {
147 switch (TYPEOF(objectSEXP))
148 {
149
150 case CHARSXP:
151 return translate(objectSEXP, asUtf8);
152
153 case STRSXP:
154 if (length(objectSEXP) == 0)
155 {
156 return std::string();
157 }
158 else
159 {
160 SEXP charSEXP = STRING_ELT(objectSEXP, 0);
161 return translate(charSEXP, asUtf8);
162 }
163
164 default:
165 Protect protect;
166 SEXP charSEXP;
167 protect.add(charSEXP = Rf_asChar(objectSEXP));
168 return translate(charSEXP, asUtf8);
169
170 }
171 }
172
173 } // anonymous namespace
174
asString(SEXP object)175 std::string asString(SEXP object)
176 {
177 return asStringImpl(object, false);
178 }
179
asUtf8String(SEXP object)180 std::string asUtf8String(SEXP object)
181 {
182 return asStringImpl(object, true);
183 }
184
safeAsString(SEXP object,const std::string & defValue)185 std::string safeAsString(SEXP object, const std::string& defValue)
186 {
187 if (object != R_NilValue)
188 return asStringImpl(object, false);
189 else
190 return defValue;
191 }
192
asInteger(SEXP object)193 int asInteger(SEXP object)
194 {
195 return Rf_asInteger(object);
196 }
197
asReal(SEXP object)198 double asReal(SEXP object)
199 {
200 return Rf_asReal(object);
201 }
202
asLogical(SEXP object)203 bool asLogical(SEXP object)
204 {
205 return Rf_asLogical(object) ? true : false;
206 }
207
fillVectorString(SEXP object,std::vector<std::string> * pVector)208 bool fillVectorString(SEXP object, std::vector<std::string>* pVector)
209 {
210 if (TYPEOF(object) != STRSXP)
211 return false;
212
213 int n = Rf_length(object);
214 pVector->reserve(pVector->size() + n);
215 for (int i = 0; i < n; i++)
216 {
217 SEXP charSEXP = STRING_ELT(object, i);
218 pVector->push_back(
219 std::string(CHAR(charSEXP), LENGTH(charSEXP)));
220 }
221
222 return true;
223 }
224
fillSetString(SEXP object,std::set<std::string> * pSet)225 bool fillSetString(SEXP object, std::set<std::string>* pSet)
226 {
227 if (TYPEOF(object) != STRSXP)
228 return false;
229
230 int n = Rf_length(object);
231 for (int i = 0; i < n; i++)
232 {
233 SEXP charSEXP = STRING_ELT(object, i);
234 pSet->insert(
235 std::string(CHAR(charSEXP), LENGTH(charSEXP)));
236 }
237
238 return true;
239 }
240
asEnvironment(std::string name)241 SEXP asEnvironment(std::string name)
242 {
243 if (name == "base")
244 return R_BaseEnv;
245
246 // prefix with 'package:' if no prefix specified yet
247 if (name.find(":") == std::string::npos)
248 name = "package:" + name;
249
250 SEXP envSEXP = ENCLOS(R_GlobalEnv);
251 while (envSEXP != R_EmptyEnv)
252 {
253 SEXP nameSEXP = Rf_getAttrib(envSEXP, R_NameSymbol);
254 if (TYPEOF(nameSEXP) == STRSXP &&
255 name == CHAR(STRING_ELT(nameSEXP, 0)))
256 {
257 return envSEXP;
258 }
259 envSEXP = ENCLOS(envSEXP);
260 }
261
262 LOG_ERROR_MESSAGE("No environment named '" + name + "' on search path");
263 return envSEXP;
264 }
265
266 namespace {
267
ensureNamespaceLoaded(const std::string & ns)268 bool ensureNamespaceLoaded(const std::string& ns)
269 {
270 if (ns.empty())
271 return false;
272
273 SEXP nsSEXP = findNamespace(ns);
274 if (nsSEXP != R_UnboundValue)
275 return true;
276
277 Error error = r::exec::RFunction("base:::requireNamespace")
278 .addParam("package", ns)
279 .addParam("quietly", true)
280 .call();
281
282 if (error)
283 return false;
284
285 return true;
286 }
287
288 } // anonymous namespace
289
asNamespace(const std::string & name)290 SEXP asNamespace(const std::string& name)
291 {
292 if (!ensureNamespaceLoaded(name))
293 return R_EmptyEnv;
294
295 return findNamespace(name);
296 }
297
forcePromise(SEXP objectSEXP)298 SEXP forcePromise(SEXP objectSEXP)
299 {
300 // if this isn't a promise, return it as-is
301 if (TYPEOF(objectSEXP) != PROMSXP)
302 return objectSEXP;
303
304 // if we already have a forced value, return that
305 SEXP valueSEXP = PRVALUE(objectSEXP);
306 if (valueSEXP != R_UnboundValue)
307 return valueSEXP;
308
309 // otherwise, evaluate the promise and return that result
310 r::sexp::Protect protect;
311 SEXP resultSEXP;
312 protect.add(resultSEXP = ::Rf_eval(PRCODE(objectSEXP), PRENV(objectSEXP)));
313
314 // update the promise reference
315 SET_PRVALUE(objectSEXP, resultSEXP);
316
317 // return the result
318 return resultSEXP;
319 }
320
findNamespace(const std::string & name)321 SEXP findNamespace(const std::string& name)
322 {
323 if (name.empty())
324 return R_UnboundValue;
325
326 // case 4071: namespace look up executes R code that can trip the debugger
327 DisableDebugScope disableStepInto(R_GlobalEnv);
328
329 // R_FindNamespace will throw if it fails to find a particular name.
330 // Instead, we manually search the namespace registry.
331 SEXP nameSEXP = Rf_install(name.c_str());
332 SEXP ns = Rf_findVarInFrame(R_NamespaceRegistry, nameSEXP);
333 return ns;
334 }
335
asPrimitiveEnvironment(SEXP envirSEXP,SEXP * pTargetSEXP,Protect * pProtect)336 Error asPrimitiveEnvironment(SEXP envirSEXP,
337 SEXP* pTargetSEXP,
338 Protect* pProtect)
339 {
340 // fast-case: no need to call back into R
341 if (TYPEOF(envirSEXP) == ENVSXP)
342 {
343 pProtect->add(*pTargetSEXP = envirSEXP);
344 return Success();
345 }
346
347 // for non-S4 objects, we can just return an error (false) early
348 if (TYPEOF(envirSEXP) != S4SXP)
349 return Error(errc::UnexpectedDataTypeError, ERROR_LOCATION);
350
351 // use R function to convert
352 Error error = RFunction("base:::as.environment")
353 .addParam(envirSEXP)
354 .call(pTargetSEXP, pProtect);
355
356 if (error)
357 return error;
358
359 // ensure that we actually succeeded in producing a primitive environment
360 if (pTargetSEXP == nullptr ||
361 *pTargetSEXP == nullptr ||
362 !isPrimitiveEnvironment(*pTargetSEXP))
363 {
364 return Error(errc::UnexpectedDataTypeError, ERROR_LOCATION);
365 }
366
367 // we have a primitive environment; all is well
368 return Success();
369 }
370
listEnvironment(SEXP env,bool includeAll,bool includeLastDotValue,Protect * pProtect,std::vector<Variable> * pVariables)371 void listEnvironment(SEXP env,
372 bool includeAll,
373 bool includeLastDotValue,
374 Protect* pProtect,
375 std::vector<Variable>* pVariables)
376 {
377 // reset passed vars
378 pVariables->clear();
379
380 // get the list of environment vars (protect locally because we
381 // we don't acutally return this list to the caller
382 SEXP envVarsSEXP;
383 Protect rProtect(envVarsSEXP = R_lsInternal(env, includeAll ? TRUE : FALSE));
384
385 // get variables
386 std::vector<std::string> vars;
387 Error error = r::sexp::extract(envVarsSEXP, &vars);
388 if (error)
389 {
390 LOG_ERROR(error);
391 return;
392 }
393
394 // add in .Last.value if it exists
395 if (!includeAll && includeLastDotValue)
396 {
397 SEXP lastValueSEXP = Rf_findVar(Rf_install(".Last.value"), env);
398 if (lastValueSEXP != R_UnboundValue)
399 vars.push_back(".Last.value");
400 }
401
402 // populate pVariables
403 for (const std::string& var : vars)
404 {
405 SEXP varSEXP = R_NilValue;
406 // Merely calling Rf_findVar on an active binding will fire the binding.
407 // Don't try to get the SEXP for the variable in this case; leave the
408 // value as nil.
409 if (!isActiveBinding(var, env))
410 varSEXP = Rf_findVar(Rf_install(var.c_str()), env);
411
412 if (varSEXP != R_UnboundValue) // should never be unbound
413 {
414 pProtect->add(varSEXP);
415 pVariables->push_back(std::make_pair(var, varSEXP));
416 }
417 else
418 {
419 LOG_WARNING_MESSAGE(
420 "Unexpected R_UnboundValue returned from R_lsInternal");
421 }
422 }
423 }
424
425
listNamedAttributes(SEXP obj,Protect * pProtect,std::vector<Variable> * pVariables)426 void listNamedAttributes(SEXP obj, Protect *pProtect, std::vector<Variable>* pVariables)
427 {
428 // reset passed vars
429 pVariables->clear();
430
431 // extract the attributes and ensure we got a pairlist
432 SEXP attrs = ATTRIB(obj);
433 if (TYPEOF(attrs) != LISTSXP)
434 return;
435
436 // extract the names from the pairlist
437 std::vector<std::string> names;
438 r::sexp::getNames(attrs, &names);
439
440 // loop over the attributes and fill in the variable vector
441 SEXP attr = R_NilValue;
442 SEXP nextAttr = R_NilValue;
443 size_t i = 0;
444 for (nextAttr = attrs; nextAttr != R_NilValue; attr = CAR(nextAttr), nextAttr = CDR(nextAttr))
445 {
446 pProtect->add(attr);
447 pVariables->push_back(std::make_pair(names.at(i), attr));
448
449 // sanity: break if we run out of names
450 if (++i >= names.size())
451 break;
452 }
453 }
454
455 namespace {
456
hasActiveBindingImpl(const std::string & name,SEXP envirSEXP,std::set<SEXP> * pVisitedObjects)457 bool hasActiveBindingImpl(const std::string& name,
458 SEXP envirSEXP,
459 std::set<SEXP>* pVisitedObjects)
460 {
461 Error error;
462 Protect protect;
463
464 // ensure we have an environment
465 if (!isEnvironment(envirSEXP))
466 return false;
467
468 // sanity check that we are working with a primitive environment
469 // (required to convert S4 objects that subclass 'environment' into
470 // a 'raw' R environment object)
471 error = asPrimitiveEnvironment(envirSEXP, &envirSEXP, &protect);
472 if (error)
473 return false;
474
475 // check for active binding
476 if (isActiveBinding(name, envirSEXP))
477 return true;
478
479 // resolve the object (discover in that frame)
480 SEXP nameSEXP = Rf_install(name.c_str());
481 SEXP varSEXP = Rf_findVarInFrame(envirSEXP, nameSEXP);
482
483 // check for special values
484 if (varSEXP == R_UnboundValue || varSEXP == R_MissingArg)
485 return false;
486
487 // ensure we're working with a primitive R environment
488 if (!isEnvironment(varSEXP))
489 return false;
490
491 error = asPrimitiveEnvironment(varSEXP, &varSEXP, &protect);
492 if (error)
493 return false;
494
495 // avoid cycles
496 if (pVisitedObjects->count(varSEXP)) return false;
497 pVisitedObjects->insert(varSEXP);
498
499 // list the bindings in this object
500 SEXP bindingsSEXP;
501 protect.add(bindingsSEXP = R_lsInternal(varSEXP, TRUE));
502
503 // iterate over items and search for active bindings
504 for (int i = 0, n = Rf_length(bindingsSEXP); i < n; ++i)
505 {
506 const char* binding = CHAR(STRING_ELT(bindingsSEXP, i));
507 if (hasActiveBindingImpl(binding, varSEXP, pVisitedObjects))
508 return true;
509 }
510
511 // no child binding has active binding; return false
512 return false;
513 }
514
515 } // end anonymous namespace
516
hasActiveBinding(const std::string & name,const SEXP envirSEXP)517 bool hasActiveBinding(const std::string& name, const SEXP envirSEXP)
518 {
519 // avoid cycles when searching recursively
520 std::set<SEXP> visitedObjects;
521 return hasActiveBindingImpl(name, envirSEXP, &visitedObjects);
522 }
523
isActiveBinding(const std::string & name,const SEXP env)524 bool isActiveBinding(const std::string& name, const SEXP env)
525 {
526 // R_BindingIsActive throws error on .Last.value check; avoid that and
527 // just assume that it's not an active binding (and hence is okay to eval)
528 if (name == ".Last.value")
529 return false;
530
531 return R_BindingIsActive(Rf_install(name.c_str()), env);
532 }
533
functionBody(SEXP functionSEXP)534 SEXP functionBody(SEXP functionSEXP)
535 {
536 if (!Rf_isFunction(functionSEXP))
537 return R_NilValue;
538
539 if (Rf_isPrimitive(functionSEXP))
540 return R_NilValue;
541
542 SEXP bodySEXP = R_NilValue;
543 Protect protect;
544 RFunction getBody("base:::body");
545 getBody.addParam(functionSEXP);
546 Error error = getBody.call(&bodySEXP, &protect);
547 if (error) LOG_ERROR(error);
548 return bodySEXP;
549 }
550
findVar(const std::string & name,const SEXP env)551 SEXP findVar(const std::string &name, const SEXP env)
552 {
553 return Rf_findVar(Rf_install(name.c_str()), env);
554 }
555
findVar(const std::string & name,const std::string & ns)556 SEXP findVar(const std::string& name, const std::string& ns)
557 {
558 if (name.empty())
559 return R_UnboundValue;
560
561 if (!ns.empty())
562 if (!ensureNamespaceLoaded(ns))
563 return R_UnboundValue;
564
565 SEXP env = ns.empty() ? R_GlobalEnv : findNamespace(ns);
566
567 return findVar(name, env);
568 }
569
570
findFunction(const std::string & name,const std::string & ns)571 SEXP findFunction(const std::string& name, const std::string& ns)
572 {
573 r::sexp::Protect protect;
574 if (name.empty())
575 return R_UnboundValue;
576
577 if (!ns.empty())
578 if (!ensureNamespaceLoaded(ns))
579 return R_UnboundValue;
580
581 SEXP env = ns.empty() ? R_GlobalEnv : findNamespace(ns);
582 if (env == R_UnboundValue) return R_UnboundValue;
583
584 // We might want to use `Rf_findFun`, but it calls `Rf_error`
585 // on failure, which involves printing the error message out
586 // to the console. To avoid this,
587 // we instead attempt to find the function by manually
588 // walking through the environment (and its enclosing environments)
589 SEXP nameSEXP = Rf_install(name.c_str());
590
591 // Search through frames until we find the global environment.
592 while (env != R_EmptyEnv)
593 {
594 // If we're searching the global environment, then
595 // try using 'Rf_findVar', as this will attempt a search
596 // of R's own internal global cache.
597 if (env == R_GlobalEnv)
598 {
599 SEXP resultSEXP = Rf_findVar(nameSEXP, R_GlobalEnv);
600 if (Rf_isFunction(resultSEXP))
601 return resultSEXP;
602 else if (TYPEOF(resultSEXP) == PROMSXP)
603 {
604 protect.add(resultSEXP = Rf_eval(resultSEXP, env));
605 if (Rf_isFunction(resultSEXP))
606 return resultSEXP;
607 }
608 }
609
610 // Otherwise, just perform a simple search through
611 // the current frame.
612 SEXP resultSEXP = Rf_findVarInFrame(env, nameSEXP);
613 if (resultSEXP != R_UnboundValue)
614 {
615 if (Rf_isFunction(resultSEXP))
616 return resultSEXP;
617 else if (TYPEOF(resultSEXP) == PROMSXP)
618 {
619 protect.add(resultSEXP = Rf_eval(resultSEXP, env));
620 if (Rf_isFunction(resultSEXP))
621 return resultSEXP;
622 }
623 }
624
625 env = ENCLOS(env);
626 }
627
628 return R_UnboundValue;
629 }
630
typeAsString(SEXP object)631 std::string typeAsString(SEXP object)
632 {
633 return Rf_type2char(TYPEOF(object));
634 }
635
classOf(SEXP objectSEXP)636 std::string classOf(SEXP objectSEXP)
637 {
638 return asString(Rf_getAttrib(objectSEXP, Rf_install("class")));
639 }
640
length(SEXP object)641 int length(SEXP object)
642 {
643 return Rf_length(object);
644 }
645
646
isLanguage(SEXP object)647 bool isLanguage(SEXP object)
648 {
649 return Rf_isLanguage(object);
650 }
651
isList(SEXP object)652 bool isList(SEXP object)
653 {
654 return TYPEOF(object) == VECSXP;
655 }
656
isString(SEXP object)657 bool isString(SEXP object)
658 {
659 return Rf_isString(object);
660 }
661
isFunction(SEXP object)662 bool isFunction(SEXP object)
663 {
664 return Rf_isFunction(object);
665 }
666
isMatrix(SEXP object)667 bool isMatrix(SEXP object)
668 {
669 return Rf_isMatrix(object);
670 }
671
isDataFrame(SEXP object)672 bool isDataFrame(SEXP object)
673 {
674 return Rf_isFrame(object);
675 }
676
isNull(SEXP object)677 bool isNull(SEXP object)
678 {
679 return Rf_isNull(object) == TRUE;
680 }
681
isPrimitiveEnvironment(SEXP object)682 bool isPrimitiveEnvironment(SEXP object)
683 {
684 return TYPEOF(object) == ENVSXP;
685 }
686
isNumeric(SEXP object)687 bool isNumeric(SEXP object)
688 {
689 return Rf_isNumeric(object);
690 }
691
isEnvironment(SEXP object)692 bool isEnvironment(SEXP object)
693 {
694 // detect primitive environments (fast path)
695 if (isPrimitiveEnvironment(object))
696 return true;
697
698 // call back to R to detect objects subclassing environment
699 if (TYPEOF(object) == S4SXP)
700 {
701 bool result = false;
702 Error error = RFunction("base:::is.environment")
703 .addParam(object)
704 .call(&result);
705
706 if (error)
707 LOG_ERROR(error);
708
709 return result;
710 }
711
712 return false;
713 }
714
getNames(SEXP sexp)715 SEXP getNames(SEXP sexp)
716 {
717 return Rf_getAttrib(sexp, R_NamesSymbol);
718 }
719
setNames(SEXP sexp,const std::vector<std::string> & names)720 bool setNames(SEXP sexp, const std::vector<std::string>& names)
721 {
722 std::size_t n = names.size();
723 if (static_cast<std::size_t>(Rf_length(sexp)) != n)
724 return false;
725
726 Rf_setAttrib(sexp,
727 R_NamesSymbol,
728 Rf_allocVector(STRSXP, names.size()));
729
730 SEXP namesSEXP = Rf_getAttrib(sexp, R_NamesSymbol);
731 for (std::size_t i = 0; i < n; ++i)
732 SET_STRING_ELT(namesSEXP, i, Rf_mkChar(names[i].c_str()));
733
734 return true;
735 }
736
getNames(SEXP sexp,std::vector<std::string> * pNames)737 Error getNames(SEXP sexp, std::vector<std::string>* pNames)
738 {
739 // attempt to get the field names
740 SEXP namesSEXP = getNames(sexp);
741
742 if (namesSEXP == R_NilValue || TYPEOF(namesSEXP) != STRSXP)
743 return Error(errc::UnexpectedDataTypeError, ERROR_LOCATION);
744 else if (Rf_length(namesSEXP) != Rf_length(sexp))
745 return Error(errc::UnexpectedDataTypeError, ERROR_LOCATION);
746
747 // copy them into the vector
748 for (int i = 0; i < Rf_length(namesSEXP); i++)
749 pNames->push_back(translate(STRING_ELT(namesSEXP, i)));
750
751 return Success();
752 }
753
getAttrib(SEXP object,SEXP attrib)754 SEXP getAttrib(SEXP object, SEXP attrib)
755 {
756 return Rf_getAttrib(object, attrib);
757 }
758
getAttrib(SEXP object,const std::string & attrib)759 SEXP getAttrib(SEXP object, const std::string& attrib)
760 {
761 return getAttrib(object, Rf_install(attrib.c_str()));
762 }
763
setAttrib(SEXP object,const std::string & attrib,SEXP val)764 SEXP setAttrib(SEXP object, const std::string& attrib, SEXP val)
765 {
766 return Rf_setAttrib(object, Rf_install(attrib.c_str()), val);
767 }
768
isExternalPointer(SEXP object)769 bool isExternalPointer(SEXP object)
770 {
771 return TYPEOF(object) == EXTPTRSXP;
772 }
773
isNullExternalPointer(SEXP object)774 bool isNullExternalPointer(SEXP object)
775 {
776 return
777 isExternalPointer(object) &&
778 R_ExternalPtrAddr(object) == nullptr;
779 }
780
makeWeakRef(SEXP key,SEXP val,R_CFinalizer_t fun,Rboolean onexit)781 SEXP makeWeakRef(SEXP key, SEXP val, R_CFinalizer_t fun, Rboolean onexit)
782 {
783 return R_MakeWeakRefC(key, val, fun, onexit);
784 }
785
registerFinalizer(SEXP s,R_CFinalizer_t fun)786 void registerFinalizer(SEXP s, R_CFinalizer_t fun)
787 {
788 R_RegisterCFinalizer(s, fun);
789 }
790
makeExternalPtr(void * ptr,R_CFinalizer_t fun,Protect * pProtect)791 SEXP makeExternalPtr(void* ptr, R_CFinalizer_t fun, Protect* pProtect)
792 {
793 SEXP s = R_MakeExternalPtr(ptr, R_NilValue, R_NilValue);
794 if (pProtect)
795 pProtect->add(s);
796 registerFinalizer(s, fun);
797 return s;
798 }
799
getExternalPtrAddr(SEXP extptr)800 void* getExternalPtrAddr(SEXP extptr)
801 {
802 return R_ExternalPtrAddr(extptr);
803 }
804
clearExternalPtr(SEXP extptr)805 void clearExternalPtr(SEXP extptr)
806 {
807 R_ClearExternalPtr(extptr);
808 }
809
getNamedListSEXP(SEXP listSEXP,const std::string & name,SEXP * pValueSEXP)810 core::Error getNamedListSEXP(SEXP listSEXP,
811 const std::string& name,
812 SEXP* pValueSEXP)
813 {
814 int valueIndex = indexOfElementNamed(listSEXP, name);
815
816 if (valueIndex != -1)
817 {
818 // get the appropriate value
819 *pValueSEXP = VECTOR_ELT(listSEXP, valueIndex);
820 return core::Success();
821 }
822 else
823 {
824 // otherwise an error
825 core::Error error(r::errc::ListElementNotFoundError, ERROR_LOCATION);
826 error.addProperty("element", name);
827 return error;
828 }
829 }
830
extract(SEXP valueSEXP,core::json::Value * pJson)831 Error extract(SEXP valueSEXP, core::json::Value* pJson)
832 {
833 return r::json::jsonValueFromObject(valueSEXP, pJson);
834 }
835
extract(SEXP valueSEXP,int * pInt)836 Error extract(SEXP valueSEXP, int* pInt)
837 {
838 if (TYPEOF(valueSEXP) != INTSXP)
839 return Error(errc::UnexpectedDataTypeError, ERROR_LOCATION);
840
841 if (Rf_length(valueSEXP) < 1)
842 return Error(errc::NoDataAvailableError, ERROR_LOCATION);
843
844 *pInt = INTEGER(valueSEXP)[0];
845 return Success();
846 }
847
extract(SEXP valueSEXP,bool * pBool)848 Error extract(SEXP valueSEXP, bool* pBool)
849 {
850 if (TYPEOF(valueSEXP) != LGLSXP)
851 return Error(errc::UnexpectedDataTypeError, ERROR_LOCATION);
852
853 if (Rf_length(valueSEXP) < 1)
854 return Error(errc::NoDataAvailableError, ERROR_LOCATION);
855
856 *pBool = LOGICAL(valueSEXP)[0] == TRUE ? true : false;
857 return Success();
858
859 }
860
extract(SEXP valueSEXP,double * pDouble)861 Error extract(SEXP valueSEXP, double* pDouble)
862 {
863 if (TYPEOF(valueSEXP) != REALSXP)
864 return Error(errc::UnexpectedDataTypeError, ERROR_LOCATION);
865
866 if (Rf_length(valueSEXP) < 1)
867 return Error(errc::NoDataAvailableError, ERROR_LOCATION);
868
869 *pDouble = REAL(valueSEXP)[0];
870 return Success();
871 }
872
extract(SEXP valueSEXP,std::vector<int> * pVector)873 Error extract(SEXP valueSEXP, std::vector<int>* pVector)
874 {
875 if (TYPEOF(valueSEXP) != INTSXP)
876 return Error(errc::UnexpectedDataTypeError, ERROR_LOCATION);
877
878 pVector->clear();
879 for (int i=0; i<Rf_length(valueSEXP); i++)
880 pVector->push_back(INTEGER(valueSEXP)[i]);
881
882 return Success();
883 }
884
extract(SEXP valueSEXP,std::string * pString,bool asUtf8)885 Error extract(SEXP valueSEXP, std::string* pString, bool asUtf8)
886 {
887 if (TYPEOF(valueSEXP) != STRSXP)
888 return Error(errc::UnexpectedDataTypeError, ERROR_LOCATION);
889
890 if (Rf_length(valueSEXP) < 1)
891 return Error(errc::NoDataAvailableError, ERROR_LOCATION);
892
893 *pString = translate(STRING_ELT(valueSEXP, 0), asUtf8);
894 return Success();
895 }
896
extract(SEXP valueSEXP,std::vector<std::string> * pVector,bool asUtf8)897 Error extract(SEXP valueSEXP, std::vector<std::string>* pVector, bool asUtf8)
898 {
899 if (TYPEOF(valueSEXP) != STRSXP)
900 return Error(errc::UnexpectedDataTypeError, ERROR_LOCATION);
901
902 pVector->clear();
903 for (int i = 0; i < Rf_length(valueSEXP); i++)
904 pVector->push_back(translate(STRING_ELT(valueSEXP, i), asUtf8));
905
906 return Success();
907 }
908
extract(SEXP valueSEXP,std::set<std::string> * pSet,bool asUtf8)909 Error extract(SEXP valueSEXP, std::set<std::string>* pSet, bool asUtf8)
910 {
911 if (TYPEOF(valueSEXP) != STRSXP)
912 return Error(errc::UnexpectedDataTypeError, ERROR_LOCATION);
913
914 pSet->clear();
915 for (int i = 0; i < Rf_length(valueSEXP); i++)
916 pSet->insert(translate(STRING_ELT(valueSEXP, i), asUtf8));
917
918 return Success();
919 }
920
extract(SEXP valueSEXP,std::map<std::string,std::set<std::string>> * pMap,bool asUtf8)921 Error extract(SEXP valueSEXP, std::map<std::string, std::set<std::string>>* pMap, bool asUtf8)
922 {
923 if (TYPEOF(valueSEXP) != VECSXP)
924 return Error(errc::UnexpectedDataTypeError, ERROR_LOCATION);
925
926 if (Rf_length(valueSEXP) == 0)
927 return Success();
928
929 SEXP namesSEXP = r::sexp::getNames(valueSEXP);
930 if (Rf_isNull(namesSEXP))
931 return Error(errc::UnexpectedDataTypeError, ERROR_LOCATION);
932
933 for (int i = 0; i < Rf_length(valueSEXP); ++i)
934 {
935 SEXP el = VECTOR_ELT(valueSEXP, i);
936 std::set<std::string> contents;
937 for (int j = 0; j < Rf_length(el); ++j)
938 contents.insert(translate(STRING_ELT(el, j), asUtf8));
939
940 std::string name = translate(STRING_ELT(namesSEXP, i), asUtf8);
941 pMap->operator [](name) = contents;
942 }
943
944 return Success();
945 }
946
extract(SEXP valueSEXP,FilePath * pFilePath)947 Error extract(SEXP valueSEXP, FilePath* pFilePath)
948 {
949 // extract result (require UTF-8)
950 std::string path;
951 Error error = extract(valueSEXP, &path, true);
952 if (error)
953 return error;
954
955 // expand aliased paths
956 path = r::util::expandFileName(path);
957
958 // return path
959 *pFilePath = FilePath(path);
960 return Success();
961 }
962
create(SEXP valueSEXP,Protect * pProtect)963 SEXP create(SEXP valueSEXP, Protect* pProtect)
964 {
965 pProtect->add(valueSEXP);
966 return valueSEXP;
967 }
968
969 namespace {
970
971 template <typename T>
createInteger(const core::json::Value & value,const std::string & type,Protect * pProtect)972 SEXP createInteger(const core::json::Value& value, const std::string& type, Protect* pProtect)
973 {
974 try
975 {
976 int casted = boost::numeric_cast<int>(value.getValue<T>());
977 return create(casted, pProtect);
978 }
979 catch(const boost::bad_numeric_cast& e)
980 {
981 LOG_DEBUG_MESSAGE("Failed to cast from " + type + " to int: " + e.what());
982 try
983 {
984 double casted = boost::numeric_cast<double>(value.getValue<T>());
985 return create(casted, pProtect);
986 }
987 CATCH_UNEXPECTED_EXCEPTION
988 }
989 CATCH_UNEXPECTED_EXCEPTION
990
991
992 // only reached if an exception occurs
993 return R_NilValue;
994 }
995
996 } // end anonymous namespace
997
create(const core::json::Value & value,Protect * pProtect)998 SEXP create(const core::json::Value& value, Protect* pProtect)
999 {
1000 // call embedded create function based on type
1001 if (value.getType() == core::json::Type::STRING)
1002 {
1003 return create(value.getString(), pProtect);
1004 }
1005 else if (value.getType() == core::json::Type::INTEGER)
1006 {
1007 if (value.isUInt64())
1008 {
1009 return createInteger<uint64_t>(value, "uint64_t", pProtect);
1010 }
1011 else if (value.isInt64())
1012 {
1013 return createInteger<int64_t>(value, "int64_t", pProtect);
1014 }
1015 else if (value.isUInt())
1016 {
1017 return createInteger<uint32_t>(value, "uint32_t", pProtect);
1018 }
1019 else if (value.isInt())
1020 {
1021 return createInteger<int32_t>(value, "int32_t", pProtect);
1022 }
1023 else
1024 {
1025 std::stringstream ss;
1026 ss << "unhandled JSON data type " << value.getType();
1027 LOG_WARNING_MESSAGE(ss.str());
1028 return R_NilValue;
1029 }
1030 }
1031 else if (value.getType() == core::json::Type::REAL)
1032 {
1033 return create(value.getDouble(), pProtect);
1034 }
1035 else if (value.getType() == core::json::Type::BOOL)
1036 {
1037 return create(value.getBool(), pProtect);
1038 }
1039 else if (value.getType() == core::json::Type::ARRAY)
1040 {
1041 return create(value.getArray(), pProtect);
1042 }
1043 else if (value.getType() == core::json::Type::OBJECT)
1044 {
1045 return create(value.getObject(), pProtect);
1046 }
1047 else
1048 {
1049 return R_NilValue;
1050 }
1051 }
1052
1053 namespace {
1054
createYamlMap(const YAML::Node & node,Protect * pProtect)1055 SEXP createYamlMap(const YAML::Node& node, Protect* pProtect)
1056 {
1057 ListBuilder builder(pProtect);
1058
1059 for (auto it = node.begin();
1060 it != node.end();
1061 ++it)
1062 {
1063 std::string key = it->first.as<std::string>();
1064 SEXP value = create(it->second, pProtect);
1065 builder.add(key, value);
1066 }
1067
1068 return r::sexp::create(builder, pProtect);
1069 }
1070
createYamlSequence(const YAML::Node & node,Protect * pProtect)1071 SEXP createYamlSequence(const YAML::Node& node, Protect* pProtect)
1072 {
1073 ListBuilder builder(pProtect);
1074
1075 for (auto it = node.begin();
1076 it != node.end();
1077 ++it)
1078 {
1079 SEXP value = create(*it, pProtect);
1080 builder.add(value);
1081 }
1082
1083 return r::sexp::create(builder, pProtect);
1084 }
1085
createYamlScalar(const YAML::Node & node,Protect * pProtect)1086 SEXP createYamlScalar(const YAML::Node& node, Protect* pProtect)
1087 {
1088 // yaml-cpp doesn't record the associated type for scalars;
1089 // we need to guess and infer for ourselves
1090 const std::string& text = node.Scalar();
1091
1092 // handle empty strings up front
1093 if (text.empty())
1094 return R_NilValue;
1095
1096 // first, handle some known keywords
1097 if (text == "null" ||
1098 text == "Null" ||
1099 text == "NULL" ||
1100 text == "~" ||
1101 text == "")
1102 {
1103 return R_NilValue;
1104 }
1105 else if (text == "true" ||
1106 text == "True" ||
1107 text == "TRUE")
1108 {
1109 return r::sexp::create(true, pProtect);
1110 }
1111 else if (text == "false" ||
1112 text == "False" ||
1113 text == "FALSE")
1114 {
1115 return r::sexp::create(false, pProtect);
1116 }
1117 else if (text == ".nan" ||
1118 text == ".NaN" ||
1119 text == ".NAN")
1120 {
1121 return r::sexp::create(R_NaReal, pProtect);
1122 }
1123 else if (text == ".inf" ||
1124 text == ".Inf" ||
1125 text == ".INF")
1126 {
1127 return r::sexp::create(R_PosInf, pProtect);
1128 }
1129 else if (text == "+.inf" ||
1130 text == "+.Inf" ||
1131 text == "+.INF")
1132 {
1133 return r::sexp::create(R_PosInf, pProtect);
1134 }
1135 else if (text == "-.inf" ||
1136 text == "-.Inf" ||
1137 text == "-.INF")
1138 {
1139 return r::sexp::create(R_NegInf, pProtect);
1140 }
1141
1142 // check for potential numeric values
1143 // (TODO: handle integers specifically?
1144 char ch = text[0];
1145 if (ch == '-' ||
1146 ch == '+' ||
1147 std::isdigit(static_cast<int>(ch)))
1148 {
1149 // first, attempt a conversion to int
1150 try
1151 {
1152 int value = node.as<int>();
1153 return r::sexp::create(value, pProtect);
1154 }
1155 catch (...)
1156 {
1157 // intentionally swallow errors
1158 }
1159
1160 // if that failed, try a conversion to double
1161 try
1162 {
1163 double value = node.as<double>();
1164 return r::sexp::create(value, pProtect);
1165 }
1166 catch (...)
1167 {
1168 // intentionally swallow errors
1169 }
1170
1171 // fall-through and parse as string
1172 }
1173
1174 // if not special conditions apply, then it's just a string
1175 return r::sexp::create(text, pProtect);
1176 }
1177
1178 } // end anonymous namespace
1179
create(const YAML::Node & node,Protect * pProtect)1180 SEXP create(const YAML::Node& node, Protect* pProtect)
1181 {
1182 auto type = node.Type();
1183 switch (type)
1184 {
1185 case YAML::NodeType::Map:
1186 return createYamlMap(node, pProtect);
1187 case YAML::NodeType::Sequence:
1188 return createYamlSequence(node, pProtect);
1189 case YAML::NodeType::Scalar:
1190 return createYamlScalar(node, pProtect);
1191 case YAML::NodeType::Undefined:
1192 case YAML::NodeType::Null:
1193 return R_NilValue;
1194 default:
1195 return R_NilValue;
1196 }
1197 }
1198
1199
1200
create(const char * value,Protect * pProtect)1201 SEXP create(const char* value, Protect* pProtect)
1202 {
1203 return create(std::string(value), pProtect);
1204 }
1205
1206 // NOTE: by default, we create strings in the _native_ encoding,
1207 // not as UTF-8 strings. this is primarily because in a number of
1208 // places we explicitly convert strings from UTF-8 to the native
1209 // encoding, and so those code paths rely on the 'value' parameter
1210 // here really being in the native encoding. we should change this
1211 // to CE_UTF8 in the future but that will require auditing all
1212 // usages of create(), of which there are many (especially through
1213 // e.g. the RFunction class)
create(const std::string & value,Protect * pProtect)1214 SEXP create(const std::string& value, Protect* pProtect)
1215 {
1216 SEXP charSEXP;
1217 pProtect->add(charSEXP = Rf_mkCharLenCE(value.c_str(), value.size(), CE_NATIVE));
1218
1219 SEXP valueSEXP;
1220 pProtect->add(valueSEXP = Rf_allocVector(STRSXP, 1));
1221
1222 SET_STRING_ELT(valueSEXP, 0, charSEXP);
1223 return valueSEXP;
1224 }
1225
create(int value,Protect * pProtect)1226 SEXP create(int value, Protect* pProtect)
1227 {
1228 SEXP valueSEXP;
1229 pProtect->add(valueSEXP = Rf_allocVector(INTSXP, 1));
1230 INTEGER(valueSEXP)[0] = value;
1231 return valueSEXP;
1232 }
1233
create(double value,Protect * pProtect)1234 SEXP create(double value, Protect* pProtect)
1235 {
1236 SEXP valueSEXP;
1237 pProtect->add(valueSEXP = Rf_allocVector(REALSXP, 1));
1238 REAL(valueSEXP)[0] = value;
1239 return valueSEXP;
1240 }
1241
create(bool value,Protect * pProtect)1242 SEXP create(bool value, Protect* pProtect)
1243 {
1244 SEXP valueSEXP;
1245 pProtect->add(valueSEXP = Rf_allocVector(LGLSXP, 1));
1246 LOGICAL(valueSEXP)[0] = value;
1247 return valueSEXP;
1248 }
1249
create(const core::json::Array & value,Protect * pProtect)1250 SEXP create(const core::json::Array& value, Protect* pProtect)
1251 {
1252 // create the list
1253 SEXP listSEXP;
1254 pProtect->add(listSEXP = Rf_allocVector(VECSXP, value.getSize()));
1255
1256 // add each array element to it
1257 for (size_t i=0; i<value.getSize(); i++)
1258 {
1259 SEXP valueSEXP = create(value[i], pProtect);
1260 SET_VECTOR_ELT(listSEXP, i, valueSEXP);
1261 }
1262 return listSEXP;
1263 }
1264
create(const core::json::Object & value,Protect * pProtect)1265 SEXP create(const core::json::Object& value, Protect* pProtect)
1266 {
1267 // create the list
1268 SEXP listSEXP;
1269 pProtect->add(listSEXP = Rf_allocVector(VECSXP, value.getSize()));
1270
1271 // build list of names
1272 SEXP namesSEXP;
1273 pProtect->add(namesSEXP = Rf_allocVector(STRSXP, value.getSize()));
1274
1275 // add each object field to it
1276 int index = 0;
1277 for (const core::json::Object::Member& member : value)
1278 {
1279 // set name
1280 SET_STRING_ELT(namesSEXP, index, Rf_mkChar(member.getName().c_str()));
1281
1282 // set value
1283 SEXP valueSEXP = create(member.getValue(), pProtect);
1284 SET_VECTOR_ELT(listSEXP, index, valueSEXP);
1285
1286 // increment element index
1287 index++;
1288 }
1289
1290 // attach names
1291 Rf_setAttrib(listSEXP, R_NamesSymbol, namesSEXP);
1292
1293 // return the list
1294 return listSEXP;
1295 }
1296
create(const std::vector<std::string> & value,Protect * pProtect)1297 SEXP create(const std::vector<std::string>& value, Protect* pProtect)
1298 {
1299 SEXP valueSEXP;
1300 pProtect->add(valueSEXP = Rf_allocVector(STRSXP, value.size()));
1301
1302 int index = 0;
1303 for (std::vector<std::string>::const_iterator
1304 it = value.begin(); it != value.end(); ++it)
1305 {
1306 SET_STRING_ELT(valueSEXP, index++, Rf_mkChar(it->c_str()));
1307 }
1308
1309 return valueSEXP;
1310 }
1311
create(const std::vector<int> & value,Protect * pProtect)1312 SEXP create(const std::vector<int>& value, Protect *pProtect)
1313 {
1314 SEXP valueSEXP;
1315 pProtect->add(valueSEXP = Rf_allocVector(INTSXP, value.size()));
1316
1317 for (std::size_t i = 0; i < value.size(); ++i)
1318 INTEGER(valueSEXP)[i] = value[i];
1319
1320 return valueSEXP;
1321 }
1322
create(const std::vector<double> & value,Protect * pProtect)1323 SEXP create(const std::vector<double>& value, Protect *pProtect)
1324 {
1325 SEXP valueSEXP;
1326 pProtect->add(valueSEXP = Rf_allocVector(REALSXP, value.size()));
1327
1328 for (std::size_t i = 0; i < value.size(); ++i)
1329 REAL(valueSEXP)[i] = value[i];
1330
1331 return valueSEXP;
1332 }
1333
create(const std::vector<bool> & value,Protect * pProtect)1334 SEXP create(const std::vector<bool>& value, Protect *pProtect)
1335 {
1336 SEXP valueSEXP;
1337 pProtect->add(valueSEXP = Rf_allocVector(LGLSXP, value.size()));
1338
1339 for (std::size_t i = 0; i < value.size(); ++i)
1340 LOGICAL(valueSEXP)[i] = value[i];
1341
1342 return valueSEXP;
1343 }
1344
1345 namespace {
secondsSinceEpoch(boost::posix_time::ptime date)1346 int secondsSinceEpoch(boost::posix_time::ptime date)
1347 {
1348 return boost::numeric_cast<int>(date_time::secondsSinceEpoch(date));
1349 }}
1350
create(const std::vector<boost::posix_time::ptime> & value,Protect * pProtect)1351 SEXP create(const std::vector<boost::posix_time::ptime>& value,
1352 Protect* pProtect)
1353 {
1354 // first create a vector of doubles containing seconds since epoch
1355 std::vector<int> seconds;
1356 std::transform(value.begin(),
1357 value.end(),
1358 std::back_inserter(seconds),
1359 secondsSinceEpoch);
1360
1361 // now turn this into an R vector and call as.POSIXct
1362 SEXP secondsSEXP = create(seconds, pProtect);
1363 SEXP posixCtSEXP = R_NilValue;
1364 r::exec::RFunction asPOSIXct("as.POSIXct", secondsSEXP);
1365 asPOSIXct.addParam("tz", "GMT");
1366 asPOSIXct.addParam("origin", "1970-01-01");
1367 Error error = asPOSIXct.call(&posixCtSEXP, pProtect);
1368 if (error)
1369 LOG_ERROR(error);
1370
1371 // return it
1372 return posixCtSEXP;
1373 }
1374
create(const std::map<std::string,std::vector<std::string>> & value,Protect * pProtect)1375 SEXP create(const std::map<std::string, std::vector<std::string> > &value,
1376 Protect *pProtect)
1377 {
1378 SEXP listSEXP, namesSEXP;
1379 std::size_t n = value.size();
1380 pProtect->add(listSEXP = Rf_allocVector(VECSXP, n));
1381 pProtect->add(namesSEXP = Rf_allocVector(STRSXP, n));
1382
1383 int index = 0;
1384 typedef std::map< std::string, std::vector<std::string> >::const_iterator iterator;
1385 for (iterator it = value.begin(); it != value.end(); ++it)
1386 {
1387 SET_STRING_ELT(namesSEXP, index, Rf_mkChar(it->first.c_str()));
1388 SET_VECTOR_ELT(listSEXP, index, r::sexp::create(it->second, pProtect));
1389 ++index;
1390 }
1391
1392 Rf_setAttrib(listSEXP, R_NamesSymbol, namesSEXP);
1393
1394 return listSEXP;
1395 }
1396
create(const std::map<std::string,SEXP> & value,Protect * pProtect)1397 SEXP create(const std::map<std::string, SEXP> &value,
1398 Protect *pProtect)
1399 {
1400 SEXP listSEXP, namesSEXP;
1401 std::size_t n = value.size();
1402 pProtect->add(listSEXP = Rf_allocVector(VECSXP, n));
1403 pProtect->add(namesSEXP = Rf_allocVector(STRSXP, n));
1404
1405 int index = 0;
1406 typedef std::map<std::string, SEXP>::const_iterator iterator;
1407 for (iterator it = value.begin(); it != value.end(); ++it)
1408 {
1409 SET_STRING_ELT(namesSEXP, index, Rf_mkChar(it->first.c_str()));
1410 SET_VECTOR_ELT(listSEXP, index, it->second);
1411 ++index;
1412 }
1413
1414 Rf_setAttrib(listSEXP, R_NamesSymbol, namesSEXP);
1415
1416 return listSEXP;
1417 }
1418
create(const std::vector<std::pair<std::string,std::string>> & value,Protect * pProtect)1419 SEXP create(const std::vector<std::pair<std::string,std::string> >& value,
1420 Protect* pProtect)
1421 {
1422 // create the character vector and the names vector
1423 SEXP charSEXP, namesSEXP;
1424 pProtect->add(charSEXP = Rf_allocVector(STRSXP, value.size()));
1425 pProtect->add(namesSEXP = Rf_allocVector(STRSXP, value.size()));
1426
1427 int index = 0;
1428 for (std::vector<std::pair<std::string,std::string> >::const_iterator
1429 it = value.begin(); it != value.end(); ++it)
1430 {
1431 // set name and value
1432 SET_STRING_ELT(namesSEXP, index, Rf_mkChar(it->first.c_str()));
1433 SET_STRING_ELT(charSEXP, index, Rf_mkChar(it->second.c_str()));
1434
1435 // increment element index
1436 index++;
1437 }
1438
1439 // attach names
1440 Rf_setAttrib(charSEXP, R_NamesSymbol, namesSEXP);
1441
1442 // return the vector
1443 return charSEXP;
1444 }
1445
create(const std::set<std::string> & value,Protect * pProtect)1446 SEXP create(const std::set<std::string> &value, Protect *pProtect)
1447 {
1448 SEXP charSEXP;
1449 pProtect->add(charSEXP = Rf_allocVector(STRSXP, value.size()));
1450
1451 int index = 0;
1452 for (std::set<std::string>::const_iterator it = value.begin();
1453 it != value.end();
1454 ++it)
1455 {
1456 SET_STRING_ELT(charSEXP, index, Rf_mkChar(it->c_str()));
1457 ++index;
1458 }
1459
1460 return charSEXP;
1461 }
1462
create(const ListBuilder & builder,Protect * pProtect)1463 SEXP create(const ListBuilder& builder, Protect *pProtect)
1464 {
1465 int n = gsl::narrow_cast<int>(builder.names().size());
1466
1467 SEXP resultSEXP;
1468 pProtect->add(resultSEXP = Rf_allocVector(VECSXP, n));
1469
1470 SEXP namesSEXP;
1471 pProtect->add(namesSEXP = Rf_allocVector(STRSXP, n));
1472
1473 for (int i = 0; i < n; i++)
1474 {
1475 SET_VECTOR_ELT(resultSEXP, i, builder.objects()[i]);
1476 SET_STRING_ELT(namesSEXP, i, Rf_mkChar(builder.names()[i].c_str()));
1477 }
1478
1479 // NOTE: empty lists are unnamed
1480 if (n > 0)
1481 Rf_setAttrib(resultSEXP, R_NamesSymbol, namesSEXP);
1482
1483 return resultSEXP;
1484 }
1485
create(const std::map<std::string,std::string> & map,Protect * pProtect)1486 SEXP create(const std::map<std::string, std::string>& map, Protect* pProtect)
1487 {
1488 std::size_t n = map.size();
1489 SEXP listSEXP;
1490 pProtect->add(listSEXP = Rf_allocVector(STRSXP, n));
1491
1492 SEXP namesSEXP;
1493 pProtect->add(namesSEXP = Rf_allocVector(STRSXP, n));
1494
1495 std::size_t i = 0;
1496 for (std::map<std::string, std::string>::const_iterator it = map.begin();
1497 it != map.end();
1498 ++it, ++i)
1499 {
1500 SET_STRING_ELT(namesSEXP, i, Rf_mkChar(it->first.c_str()));
1501 SET_STRING_ELT(listSEXP, i, Rf_mkChar(it->second.c_str()));
1502 }
1503
1504 Rf_setAttrib(listSEXP, R_NamesSymbol, namesSEXP);
1505 return listSEXP;
1506 }
1507
createUtf8(const std::string & data,Protect * pProtect)1508 SEXP createUtf8(const std::string& data, Protect* pProtect)
1509 {
1510 SEXP strSEXP;
1511 pProtect->add(strSEXP = Rf_allocVector(STRSXP, 1));
1512
1513 SEXP charSEXP;
1514 pProtect->add(charSEXP = Rf_mkCharLenCE(data.c_str(), data.size(), CE_UTF8));
1515
1516 SET_STRING_ELT(strSEXP, 0, charSEXP);
1517 return strSEXP;
1518 }
1519
createUtf8(const FilePath & filePath,Protect * pProtect)1520 SEXP createUtf8(const FilePath& filePath, Protect* pProtect)
1521 {
1522 return createUtf8(filePath.getAbsolutePath(), pProtect);
1523 }
1524
createRawVector(const std::string & data,Protect * pProtect)1525 SEXP createRawVector(const std::string& data, Protect* pProtect)
1526 {
1527 SEXP rawSEXP;
1528 pProtect->add(rawSEXP = Rf_allocVector(RAWSXP, data.size()));
1529 ::memcpy(RAW(rawSEXP), data.c_str(), data.size());
1530 return rawSEXP;
1531 }
1532
createList(const std::vector<std::string> & names,Protect * pProtect)1533 SEXP createList(const std::vector<std::string>& names, Protect* pProtect)
1534 {
1535 std::size_t n = names.size();
1536 SEXP listSEXP;
1537 pProtect->add(listSEXP = Rf_allocVector(VECSXP, n));
1538
1539 SEXP namesSEXP;
1540 pProtect->add(namesSEXP = Rf_allocVector(STRSXP, n));
1541 for (std::size_t i = 0; i < n; ++i)
1542 SET_STRING_ELT(namesSEXP, i, Rf_mkChar(names[i].c_str()));
1543
1544 Rf_setAttrib(listSEXP, R_NamesSymbol, namesSEXP);
1545
1546 return listSEXP;
1547 }
1548
~Protect()1549 Protect::~Protect()
1550 {
1551 try
1552 {
1553 unprotectAll();
1554 }
1555 catch(...)
1556 {
1557 }
1558 }
1559
add(SEXP sexp)1560 void Protect::add(SEXP sexp)
1561 {
1562 PROTECT(sexp);
1563 protectCount_++;
1564 }
1565
unprotectAll()1566 void Protect::unprotectAll()
1567 {
1568 if (protectCount_ > 0)
1569 UNPROTECT(protectCount_);
1570 protectCount_ = 0;
1571 }
1572
1573
PreservedSEXP()1574 PreservedSEXP::PreservedSEXP()
1575 : sexp_(R_NilValue)
1576 {
1577 }
1578
PreservedSEXP(SEXP sexp)1579 PreservedSEXP::PreservedSEXP(SEXP sexp)
1580 : sexp_(R_NilValue)
1581 {
1582 set(sexp);
1583 }
1584
set(SEXP sexp)1585 void PreservedSEXP::set(SEXP sexp)
1586 {
1587 releaseNow();
1588 sexp_ = sexp;
1589 if (sexp_ != R_NilValue)
1590 ::R_PreserveObject(sexp_);
1591 }
1592
~PreservedSEXP()1593 PreservedSEXP::~PreservedSEXP()
1594 {
1595 try
1596 {
1597 releaseNow();
1598 }
1599 catch(...)
1600 {
1601 }
1602 }
1603
releaseNow()1604 void PreservedSEXP::releaseNow()
1605 {
1606 if (sexp_ != R_NilValue)
1607 {
1608 ::R_ReleaseObject(sexp_);
1609 sexp_ = R_NilValue;
1610 }
1611 }
1612
add(SEXP dataSEXP)1613 SEXP SEXPPreserver::add(SEXP dataSEXP)
1614 {
1615 if (dataSEXP != R_NilValue)
1616 {
1617 ::R_PreserveObject(dataSEXP);
1618 preservedSEXPs_.push_back(dataSEXP);
1619 }
1620 return dataSEXP;
1621 }
1622
~SEXPPreserver()1623 SEXPPreserver::~SEXPPreserver()
1624 {
1625 for (std::size_t i = 0, n = preservedSEXPs_.size(); i < n; ++i)
1626 ::R_ReleaseObject(preservedSEXPs_[n - i - 1]);
1627 }
1628
printValue(SEXP object)1629 void printValue(SEXP object)
1630 {
1631 Error error = r::exec::executeSafely(
1632 boost::bind(Rf_PrintValue, object)
1633 );
1634
1635 if (error)
1636 LOG_ERROR(error);
1637 }
1638
inherits(SEXP object,const char * S3Class)1639 bool inherits(SEXP object, const char* S3Class)
1640 {
1641 return Rf_inherits(object, S3Class);
1642 }
1643
makeNsePrimitives()1644 std::set<std::string> makeNsePrimitives()
1645 {
1646 std::set<std::string> nsePrimitives;
1647 nsePrimitives.insert("quote");
1648 nsePrimitives.insert("substitute");
1649 nsePrimitives.insert("match.call");
1650 nsePrimitives.insert("library");
1651 nsePrimitives.insert("require");
1652 nsePrimitives.insert("enquote");
1653 nsePrimitives.insert("bquote");
1654 nsePrimitives.insert("expression");
1655 nsePrimitives.insert("evalq");
1656 nsePrimitives.insert("subset");
1657 nsePrimitives.insert("eval.parent");
1658 nsePrimitives.insert("sys.call");
1659 nsePrimitives.insert("sys.calls");
1660 nsePrimitives.insert("sys.frame");
1661 nsePrimitives.insert("sys.frames");
1662 nsePrimitives.insert("sys.function");
1663 nsePrimitives.insert("sys.parent");
1664 nsePrimitives.insert("lazy_dots");
1665 return nsePrimitives;
1666 }
1667
nsePrimitives()1668 const std::set<std::string>& nsePrimitives()
1669 {
1670 static const std::set<std::string> set = makeNsePrimitives();
1671 return set;
1672 }
1673
isNSEPrimitiveSymbolOrString(SEXP objectSEXP,const std::set<std::string> & nsePrimitives)1674 bool isNSEPrimitiveSymbolOrString(
1675 SEXP objectSEXP,
1676 const std::set<std::string>& nsePrimitives)
1677 {
1678 if (TYPEOF(objectSEXP) == SYMSXP)
1679 return nsePrimitives.count(CHAR(PRINTNAME(objectSEXP)));
1680 else if (TYPEOF(objectSEXP) == STRSXP && length(objectSEXP) == 1)
1681 return nsePrimitives.count(CHAR(STRING_ELT(objectSEXP, 0)));
1682
1683 return false;
1684 }
1685
isCallToNSEFunction(SEXP nodeSEXP,const std::set<std::string> & nsePrimitives,bool * pResult)1686 bool isCallToNSEFunction(SEXP nodeSEXP,
1687 const std::set<std::string>& nsePrimitives,
1688 bool* pResult)
1689 {
1690 if (nodeSEXP == nullptr)
1691 return false;
1692
1693 if (TYPEOF(nodeSEXP) == LANGSXP)
1694 {
1695 SEXP headSEXP = CAR(nodeSEXP);
1696 if (TYPEOF(headSEXP) == SYMSXP)
1697 {
1698 const char* name = CHAR(PRINTNAME(headSEXP));
1699 if (nsePrimitives.count(name))
1700 {
1701 *pResult = true;
1702 return true;
1703 }
1704
1705 if (strcmp(name, "::") == 0 || strcmp(name, ":::") == 0)
1706 {
1707 SEXP fnSEXP = CADDR(nodeSEXP);
1708 if (isNSEPrimitiveSymbolOrString(fnSEXP, nsePrimitives))
1709 {
1710 *pResult = true;
1711 return true;
1712 }
1713 }
1714 }
1715 }
1716 return false;
1717 }
1718
1719 // Attempts to find calls to functions which perform NSE.
maybePerformsNSEImpl(SEXP node,const std::set<std::string> & nsePrimitives)1720 bool maybePerformsNSEImpl(SEXP node,
1721 const std::set<std::string>& nsePrimitives)
1722 {
1723 r::sexp::CallRecurser recurser(node);
1724 bool result = false;
1725 recurser.add(boost::bind(
1726 isCallToNSEFunction, _1,
1727 boost::cref(nsePrimitives), &result));
1728 recurser.run();
1729 return result;
1730 }
1731
makeKnownNSEFunctions()1732 std::set<SEXP> makeKnownNSEFunctions()
1733 {
1734 std::set<SEXP> set;
1735
1736 // .Internal performs lookup of functions in a way
1737 // not readily exposed (nor available in the evaluation env)
1738 set.insert(findFunction(".Internal", "base"));
1739
1740 set.insert(findFunction("with", "base"));
1741 set.insert(findFunction("within", "base"));
1742
1743 // TODO: These don't really perform NSE, but the symbols
1744 // used for '.Call' are not generated in a way that we can
1745 // easily detect until the package is actually built.
1746 set.insert(findFunction(".Call", "base"));
1747 set.insert(findFunction(".C", "base"));
1748 set.insert(findFunction(".Fortran", "base"));
1749 set.insert(findFunction(".External", "base"));
1750
1751 return set;
1752 }
1753
isKnownNseFunction(SEXP functionSEXP)1754 bool isKnownNseFunction(SEXP functionSEXP)
1755 {
1756 static const std::set<SEXP> knownNseFunctions = makeKnownNSEFunctions();
1757 return core::algorithm::contains(knownNseFunctions, functionSEXP);
1758 }
1759
maybePerformsNSE(SEXP functionSEXP)1760 bool maybePerformsNSE(SEXP functionSEXP)
1761 {
1762 if (isKnownNseFunction(functionSEXP))
1763 return true;
1764
1765 if (!Rf_isFunction(functionSEXP))
1766 return false;
1767
1768 if (Rf_isPrimitive(functionSEXP))
1769 return false;
1770
1771 return maybePerformsNSEImpl(
1772 functionBody(functionSEXP),
1773 nsePrimitives());
1774 }
1775
1776 // NOTE: Uses `R_lsInternal` which throws error if a non-environment is
1777 // passed; we therefore perform this validation ourselves before calling
1778 // `R_lsInternal`. This is primarily done to avoid the error being printed
1779 // out to the R console.
objects(SEXP environment,bool allNames,Protect * pProtect)1780 SEXP objects(SEXP environment,
1781 bool allNames,
1782 Protect* pProtect)
1783 {
1784 if (TYPEOF(environment) != ENVSXP)
1785 {
1786 LOG_ERROR_MESSAGE("'objects' called on non-environment");
1787 return R_NilValue;
1788 }
1789
1790 SEXP resultSEXP;
1791 pProtect->add(resultSEXP = R_lsInternal(environment, allNames ? TRUE : FALSE));
1792 return resultSEXP;
1793 }
1794
objects(SEXP environment,bool allNames,std::vector<std::string> * pNames)1795 Error objects(SEXP environment,
1796 bool allNames,
1797 std::vector<std::string>* pNames)
1798 {
1799 Protect protect;
1800 SEXP objectsSEXP = objects(environment, allNames, &protect);
1801
1802 if (Rf_isNull(objectsSEXP))
1803 return Error(errc::CodeExecutionError, ERROR_LOCATION);
1804
1805 if (!fillVectorString(objectsSEXP, pNames))
1806 return Error(errc::CodeExecutionError, ERROR_LOCATION);
1807
1808 return Success();
1809 }
1810
getNamespaceExports(SEXP ns,std::vector<std::string> * pNames)1811 core::Error getNamespaceExports(SEXP ns,
1812 std::vector<std::string>* pNames)
1813 {
1814 r::exec::RFunction f("getNamespaceExports");
1815 f.addParam(ns);
1816 Error error = f.call(pNames);
1817 if (error)
1818 LOG_ERROR(error);
1819 return error;
1820 }
1821
1822 namespace detail {
1823
addSymbolCheckedForMissingness(SEXP nodeSEXP,StringSet * pSymbolsCheckedForMissingness)1824 bool addSymbolCheckedForMissingness(
1825 SEXP nodeSEXP,
1826 StringSet* pSymbolsCheckedForMissingness)
1827 {
1828 if (TYPEOF(nodeSEXP) == LANGSXP &&
1829 TYPEOF(CAR(nodeSEXP)) == SYMSXP &&
1830 CDR(nodeSEXP) != R_NilValue &&
1831 TYPEOF(CADR(nodeSEXP)) == SYMSXP &&
1832 CDDR(nodeSEXP) == R_NilValue &&
1833 strcmp(CHAR(PRINTNAME(CAR(nodeSEXP))), "missing") == 0)
1834 {
1835 DEBUG("Handling 'missing(" << CHAR(PRINTNAME(CADR(nodeSEXP))) << ")'");
1836 pSymbolsCheckedForMissingness->insert(CHAR(PRINTNAME(CADR(nodeSEXP))));
1837 }
1838 return false;
1839 }
1840
addSymbols(SEXP nodeSEXP,StringSet * pSymbolsUsed)1841 bool addSymbols(
1842 SEXP nodeSEXP,
1843 StringSet* pSymbolsUsed)
1844 {
1845 if (TYPEOF(nodeSEXP) == SYMSXP)
1846 {
1847 DEBUG("Reporting symbol '" << CHAR(PRINTNAME(nodeSEXP)) << "' as used");
1848 pSymbolsUsed->insert(CHAR(PRINTNAME(nodeSEXP)));
1849 }
1850 return false;
1851 }
1852
examineSymbolUsage(SEXP nodeSEXP,FunctionSymbolUsage * usage)1853 void examineSymbolUsage(
1854 SEXP nodeSEXP,
1855 FunctionSymbolUsage* usage)
1856 {
1857 CallRecurser recurser(nodeSEXP);
1858 recurser.add(boost::bind(addSymbols, _1, &(usage->symbolsUsed)));
1859 recurser.add(boost::bind(addSymbolCheckedForMissingness, _1,
1860 &(usage->symbolsCheckedForMissingness)));
1861 recurser.run();
1862 }
1863
1864 } // namespace detail
1865
examineSymbolUsage(SEXP functionSEXP,FunctionInformation * pInfo)1866 void examineSymbolUsage(
1867 SEXP functionSEXP,
1868 FunctionInformation* pInfo)
1869 {
1870 if (Rf_isPrimitive(functionSEXP))
1871 return;
1872
1873 SEXP bodySEXP = functionBody(functionSEXP);
1874
1875 FunctionSymbolUsageCache& cache = functionSymbolUsageCache();
1876 FunctionSymbolUsage usage;
1877
1878 if (cache.contains(functionSEXP))
1879 {
1880 usage = cache.get(functionSEXP);
1881 }
1882 else
1883 {
1884 detail::examineSymbolUsage(bodySEXP, &usage);
1885 cache.put(functionSEXP, usage);
1886 }
1887
1888 // fill output
1889 for (FormalInformation& info : pInfo->formals())
1890 {
1891 const std::string& name = info.name();
1892 info.setIsUsed(usage.symbolsUsed.contains(name.c_str()));
1893
1894 bool isInternalFunction =
1895 usage.symbolsUsed.contains(".Internal") ||
1896 usage.symbolsUsed.contains(".Primitive");
1897
1898 info.setMissingnessHandled(
1899 isInternalFunction ||
1900 usage.symbolsCheckedForMissingness.contains(name.c_str()));
1901 }
1902 }
1903
1904 class PrimitiveWrappers : boost::noncopyable
1905 {
1906
1907 public:
1908
operator [](SEXP primitiveSEXP)1909 SEXP operator[](SEXP primitiveSEXP)
1910 {
1911 if (contains(primitiveSEXP))
1912 return get(primitiveSEXP);
1913
1914 r::sexp::Protect protect;
1915 SEXP wrapperSEXP = R_NilValue;
1916 r::exec::RFunction makePrimitiveWrapper(".rs.makePrimitiveWrapper");
1917 makePrimitiveWrapper.addParam(primitiveSEXP);
1918 Error error = makePrimitiveWrapper.call(&wrapperSEXP, &protect);
1919 if (error)
1920 LOG_ERROR(error);
1921
1922 put(primitiveSEXP, wrapperSEXP);
1923 return wrapperSEXP;
1924 }
1925
1926 private:
contains(SEXP primitiveSEXP)1927 bool contains(SEXP primitiveSEXP)
1928 {
1929 return database_.count(primitiveSEXP);
1930 }
1931
get(SEXP primitiveSEXP)1932 SEXP get(SEXP primitiveSEXP)
1933 {
1934 return database_[primitiveSEXP];
1935 }
1936
put(SEXP primitiveSEXP,SEXP wrapperSEXP)1937 void put(SEXP primitiveSEXP, SEXP wrapperSEXP)
1938 {
1939 if (wrapperSEXP != R_NilValue)
1940 R_PreserveObject(wrapperSEXP);
1941 database_[primitiveSEXP] = wrapperSEXP;
1942 }
1943
1944 std::map<SEXP, SEXP> database_;
1945 };
1946
primitiveWrappers()1947 PrimitiveWrappers& primitiveWrappers()
1948 {
1949 static PrimitiveWrappers instance;
1950 return instance;
1951 }
1952
primitiveWrapper(SEXP primitiveSEXP)1953 SEXP primitiveWrapper(SEXP primitiveSEXP)
1954 {
1955 PrimitiveWrappers& wrappers = primitiveWrappers();
1956 return wrappers[primitiveSEXP];
1957 }
1958
extractFunctionInfo(SEXP functionSEXP,FunctionInformation * pInfo,bool extractDefaultArguments,bool recordSymbolUsage)1959 core::Error extractFunctionInfo(
1960 SEXP functionSEXP,
1961 FunctionInformation* pInfo,
1962 bool extractDefaultArguments,
1963 bool recordSymbolUsage)
1964 {
1965 r::sexp::Protect protect;
1966 if (!Rf_isFunction(functionSEXP))
1967 return Error(errc::UnexpectedDataTypeError, ERROR_LOCATION);
1968
1969 // Primitives don't actually have formals attached to them -- they are
1970 // instead contained in a separate environment, and looking up those
1971 // arguments involves the use of unexported (hidden) R functions. So,
1972 // we mock the whole process by mapping primitive SEXPs to dummy functions
1973 // which contain the appropriate formals.
1974 bool isPrimitive = Rf_isPrimitive(functionSEXP);
1975 pInfo->setIsPrimitive(isPrimitive);
1976 if (isPrimitive)
1977 {
1978 functionSEXP = primitiveWrapper(functionSEXP);
1979 if (functionSEXP == R_NilValue)
1980 return Error(errc::UnexpectedDataTypeError, ERROR_LOCATION);
1981 }
1982
1983 // TODO: Some primitives (e.g. language constructs like `if`, `return`)
1984 // still do not have formals; these functions only take arguments
1985 // by position and so don't fit into this function's mold.
1986 if (Rf_isPrimitive(functionSEXP))
1987 return Success();
1988
1989 SEXP formals = FORMALS(functionSEXP);
1990
1991 // NOTE: 'as.character' has different behaviour for pairlist of calls vs.
1992 // a call itself; we desire the behaviour associated with pairlists of
1993 // calls (it generates a character vector, with the default values that
1994 // the formals take as entries in that character vector). However, it does
1995 // not distinguish between the case of having no default value, and an
1996 // empty string as a default value, so we handle that specially.
1997 SEXP defaultValues = R_NilValue;
1998 if (extractDefaultArguments)
1999 protect.add(defaultValues = Rf_coerceVector(formals, STRSXP));
2000
2001 // Iterate through the formals pairlist and append tag names
2002 // to the output.
2003 std::size_t index = 0;
2004 while (formals != R_NilValue)
2005 {
2006 FormalInformation formalInfo(CHAR(PRINTNAME(TAG(formals))));
2007 if (extractDefaultArguments)
2008 {
2009 if (CAR(formals) != R_MissingArg)
2010 {
2011 formalInfo.setDefaultValue(
2012 CHAR(STRING_ELT(defaultValues, index)));
2013 }
2014 }
2015
2016 formals = CDR(formals);
2017 ++index;
2018 pInfo->addFormal(formalInfo);
2019 }
2020
2021 // Certain callers will want detailed information about how formals are
2022 // actually used by this function.
2023 if (recordSymbolUsage)
2024 examineSymbolUsage(functionSEXP, pInfo);
2025
2026 return Success();
2027 }
2028
2029 namespace {
2030
addressAsString(void * ptr)2031 std::string addressAsString(void* ptr)
2032 {
2033 // NOTE: over-allocating but whatever
2034 char buf[33];
2035 snprintf(buf, 32, "<%p>", ptr);
2036 return buf;
2037 }
2038
2039 } // anonymous namespace
2040
2041 // NOTE: accept both functions and environments
2042 // for functions, we return the name of the enclosing environment
environmentName(SEXP envSEXP)2043 std::string environmentName(SEXP envSEXP)
2044 {
2045 if (Rf_isPrimitive(envSEXP))
2046 return "base";
2047
2048 if (Rf_isFunction(envSEXP))
2049 envSEXP = CLOENV(envSEXP);
2050
2051 if (TYPEOF(envSEXP) != ENVSXP)
2052 return "<unknown>";
2053
2054 if (envSEXP == R_GlobalEnv)
2055 return "R_GlobalEnv";
2056 else if (envSEXP == R_BaseEnv)
2057 return "base";
2058 else if (R_IsPackageEnv(envSEXP))
2059 return std::string("package:") +
2060 CHAR(STRING_ELT(R_PackageEnvName(envSEXP), 0));
2061 else if (R_IsNamespaceEnv(envSEXP))
2062 return std::string("namespace:") +
2063 CHAR(STRING_ELT(R_NamespaceEnvSpec(envSEXP), 0));
2064 else
2065 return addressAsString((void*) envSEXP);
2066 }
2067
2068 } // namespace sexp
2069 } // namespace r
2070 } // namespace rstudio
2071