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