1 #include "debug.h"
2 #include "utils.h"
3 #include <R.h>
4 #include <unistd.h>
5 #include <stdio.h>
6 #include <stdarg.h>
7 
8 // For debug.h
9 #if defined(DEBUG_THREAD)
10 tct_thrd_t __main_thread__;
11 tct_thrd_t __background_thread__;
12 #endif
13 
14 
15 // It's not safe to call REprintf from the background thread but we need some
16 // way to output error messages. R CMD check does not it if the code uses the
17 // symbols stdout, stderr, and printf, so this function is a way to avoid
18 // those. It's to calling `fprintf(stderr, ...)`.
err_printf(const char * fmt,...)19 void err_printf(const char *fmt, ...) {
20   const size_t max_size = 4096;
21   char buf[max_size];
22 
23   va_list args;
24   va_start(args, fmt);
25   int n = vsnprintf(buf, max_size, fmt, args);
26   va_end(args);
27 
28   if (n == -1)
29     return;
30 
31   ssize_t res = write(STDERR_FILENO, buf, n);
32   // This is here simply to avoid a warning about "ignoring return value" of
33   // the write(), on some compilers. (Seen with gcc 4.4.7 on RHEL 6)
34   res += 0;
35 }
36 
37 // Set the default log level
38 LogLevel log_level_ = LOG_ERROR;
39 
40 
41 // Sets the current log level and returns previous value.
42 // [[Rcpp::export]]
log_level(std::string level)43 std::string log_level(std::string level) {
44   LogLevel old_level = log_level_;
45 
46   if (level == "") {
47     // Do nothing
48   } else if (level == "OFF") {
49     log_level_ = LOG_OFF;
50   } else if (level == "ERROR") {
51     log_level_ = LOG_ERROR;
52   } else if (level == "WARN") {
53     log_level_ = LOG_WARN;
54   } else if (level == "INFO") {
55     log_level_ = LOG_INFO;
56   } else if (level == "DEBUG") {
57     log_level_ = LOG_DEBUG;
58   } else {
59     Rf_error("Unknown value for `level`");
60   }
61 
62   switch(old_level) {
63     case LOG_OFF:   return "OFF";
64     case LOG_ERROR: return "ERROR";
65     case LOG_WARN:  return "WARN";
66     case LOG_INFO:  return "INFO";
67     case LOG_DEBUG: return "DEBUG";
68     default:        return "";
69   }
70 }
71 
72 // Reports whether package was compiled with UBSAN
73 // [[Rcpp::export]]
using_ubsan()74 bool using_ubsan() {
75 #ifdef USING_UBSAN
76   return true;
77 #else
78   return false;
79 #endif
80 }
81