1 
2 #include "errors.h"
3 
4 #include <Rinternals.h>
5 
6 #include <string.h>
7 
8 #define ERRORBUF_SIZE 4096
9 static char errorbuf[ERRORBUF_SIZE];
10 
r_throw_error(const char * func,const char * filename,int line,const char * msg,...)11 SEXP r_throw_error(const char *func, const char *filename, int line,
12                    const char *msg, ...) {
13   va_list args;
14   errorbuf[0] = '\0';
15   va_start(args, msg);
16   vsnprintf(errorbuf, ERRORBUF_SIZE, msg, args);
17   va_end (args);
18   error("%s @%s:%d (%s)", errorbuf, filename, line, func);
19   return R_NilValue;
20 }
21 
22 #ifdef _WIN32
23 
r_throw_system_error(const char * func,const char * filename,int line,DWORD errorcode,const char * sysmsg,const char * msg,...)24 SEXP r_throw_system_error(const char *func, const char *filename, int line,
25                           DWORD errorcode, const char *sysmsg,
26                           const char *msg, ...) {
27 
28   va_list args;
29   LPVOID lpMsgBuf;
30   char *realsysmsg = sysmsg ? (char*) sysmsg : NULL;
31   char *failmsg = "Formatting the system message failed :(";
32 
33   if (errorcode == -1) errorcode = GetLastError();
34 
35   if (!realsysmsg) {
36     DWORD ret = FormatMessage(
37       FORMAT_MESSAGE_ALLOCATE_BUFFER |
38       FORMAT_MESSAGE_FROM_SYSTEM |
39       FORMAT_MESSAGE_IGNORE_INSERTS,
40       NULL,
41       errorcode,
42       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
43       (LPTSTR) &lpMsgBuf,
44       0, NULL);
45 
46     if (ret == 0) {
47       realsysmsg = failmsg;
48     } else {
49       realsysmsg = R_alloc(1, strlen(lpMsgBuf) + 1);
50       strcpy(realsysmsg, lpMsgBuf);
51       LocalFree(lpMsgBuf);
52     }
53   }
54 
55   errorbuf[0] = '\0';
56   va_start(args, msg);
57   vsnprintf(errorbuf, ERRORBUF_SIZE, msg, args);
58   va_end(args);
59   error("%s (system error %d, %s) @%s:%d (%s)", errorbuf, errorcode,
60         realsysmsg, filename, line, func);
61   return R_NilValue;
62 }
63 
64 #endif
65 
66 #ifdef _WIN32
r_throw_posix_error(const char * func,const char * filename,int line,int errorcode,const char * sysmsg,const char * msg,...)67 SEXP r_throw_posix_error(
68 #else
69 SEXP r_throw_system_error(
70 #endif
71                           const char *func, const char *filename, int line,
72                           int errorcode, const char *sysmsg,
73                           const char *msg, ...) {
74   va_list args;
75   if (!sysmsg) sysmsg = strerror(errorcode);
76   errorbuf[0] = '\0';
77   va_start(args, msg);
78   vsnprintf(errorbuf, ERRORBUF_SIZE, msg, args);
79   va_end(args);
80   error("%s (system error %d, %s) @%s:%d (%s)", errorbuf, errorcode, sysmsg,
81         filename, line, func);
82   return R_NilValue;
83 }
84