SDL  2.0
SDL_error.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "./SDL_internal.h"
22 
23 /* Simple error handling in SDL */
24 
25 #include "SDL_log.h"
26 #include "SDL_error.h"
27 #include "SDL_error_c.h"
28 
29 
30 /* Routine to get the thread-specific error variable */
31 #if SDL_THREADS_DISABLED
32 /* The default (non-thread-safe) global error variable */
33 static SDL_error SDL_global_error;
34 #define SDL_GetErrBuf() (&SDL_global_error)
35 #else
36 extern SDL_error *SDL_GetErrBuf(void);
37 #endif /* SDL_THREADS_DISABLED */
38 
39 #define SDL_ERRBUFIZE 1024
40 
41 /* Private functions */
42 
43 static const char *
44 SDL_LookupString(const char *key)
45 {
46  /* FIXME: Add code to lookup key in language string hash-table */
47  return key;
48 }
49 
50 /* Public functions */
51 
52 int
54 {
55  va_list ap;
56  SDL_error *error;
57 
58  /* Ignore call if invalid format pointer was passed */
59  if (fmt == NULL) return -1;
60 
61  /* Copy in the key, mark error as valid */
62  error = SDL_GetErrBuf();
63  error->error = 1;
64  SDL_strlcpy((char *) error->key, fmt, sizeof(error->key));
65 
66  va_start(ap, fmt);
67  error->argc = 0;
68  while (*fmt) {
69  if (*fmt++ == '%') {
70  while (*fmt == '.' || (*fmt >= '0' && *fmt <= '9')) {
71  ++fmt;
72  }
73  switch (*fmt++) {
74  case 0: /* Malformed format string.. */
75  --fmt;
76  break;
77  case 'c':
78  case 'i':
79  case 'd':
80  case 'u':
81  case 'o':
82  case 'x':
83  case 'X':
84  error->args[error->argc++].value_i = va_arg(ap, int);
85  break;
86  case 'f':
87  error->args[error->argc++].value_f = va_arg(ap, double);
88  break;
89  case 'p':
90  error->args[error->argc++].value_ptr = va_arg(ap, void *);
91  break;
92  case 's':
93  {
94  int i = error->argc;
95  const char *str = va_arg(ap, const char *);
96  if (str == NULL)
97  str = "(null)";
98  SDL_strlcpy((char *) error->args[i].buf, str,
100  error->argc++;
101  }
102  break;
103  default:
104  break;
105  }
106  if (error->argc >= ERR_MAX_ARGS) {
107  break;
108  }
109  }
110  }
111  va_end(ap);
112 
113  /* If we are in debug mode, print out an error message */
115 
116  return -1;
117 }
118 
119 #ifdef __GNUC__
120 #pragma GCC diagnostic push
121 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
122 #endif
123 /* This function has a bit more overhead than most error functions
124  so that it supports internationalization and thread-safe errors.
125 */
126 static char *
127 SDL_GetErrorMsg(char *errstr, int maxlen)
128 {
129  SDL_error *error;
130 
131  /* Clear the error string */
132  *errstr = '\0';
133  --maxlen;
134 
135  /* Get the thread-safe error, and print it out */
136  error = SDL_GetErrBuf();
137  if (error->error) {
138  const char *fmt;
139  char *msg = errstr;
140  int len;
141  int argi;
142 
143  fmt = SDL_LookupString(error->key);
144  argi = 0;
145  while (*fmt && (maxlen > 0)) {
146  if (*fmt == '%') {
147  char tmp[32], *spot = tmp;
148  *spot++ = *fmt++;
149  while ((*fmt == '.' || (*fmt >= '0' && *fmt <= '9'))
150  && spot < (tmp + SDL_arraysize(tmp) - 2)) {
151  *spot++ = *fmt++;
152  }
153  *spot++ = *fmt++;
154  *spot++ = '\0';
155  switch (spot[-2]) {
156  case '%':
157  *msg++ = '%';
158  maxlen -= 1;
159  break;
160  case 'c':
161  case 'i':
162  case 'd':
163  case 'u':
164  case 'o':
165  case 'x':
166  case 'X':
167  len =
168  SDL_snprintf(msg, maxlen, tmp,
169  error->args[argi++].value_i);
170  if (len > 0) {
171  msg += len;
172  maxlen -= len;
173  }
174  break;
175 
176  case 'f':
177  len =
178  SDL_snprintf(msg, maxlen, tmp,
179  error->args[argi++].value_f);
180  if (len > 0) {
181  msg += len;
182  maxlen -= len;
183  }
184  break;
185 
186  case 'p':
187  len =
188  SDL_snprintf(msg, maxlen, tmp,
189  error->args[argi++].value_ptr);
190  if (len > 0) {
191  msg += len;
192  maxlen -= len;
193  }
194  break;
195 
196  case 's':
197  len =
198  SDL_snprintf(msg, maxlen, tmp,
199  SDL_LookupString(error->args[argi++].
200  buf));
201  if (len > 0) {
202  msg += len;
203  maxlen -= len;
204  }
205  break;
206 
207  }
208  } else {
209  *msg++ = *fmt++;
210  maxlen -= 1;
211  }
212  }
213 
214  /* slide back if we've overshot the end of our buffer. */
215  if (maxlen < 0) {
216  msg -= (-maxlen) + 1;
217  }
218 
219  *msg = 0; /* NULL terminate the string */
220  }
221  return (errstr);
222 }
223 #ifdef __GNUC__
224 #pragma GCC diagnostic pop
225 #endif
226 
227 /* Available for backwards compatibility */
228 const char *
230 {
231  static char errmsg[SDL_ERRBUFIZE];
232 
233  return SDL_GetErrorMsg(errmsg, SDL_ERRBUFIZE);
234 }
235 
236 void
238 {
239  SDL_error *error;
240 
241  error = SDL_GetErrBuf();
242  error->error = 0;
243 }
244 
245 /* Very common errors go here */
246 int
248 {
249  switch (code) {
250  case SDL_ENOMEM:
251  return SDL_SetError("Out of memory");
252  case SDL_EFREAD:
253  return SDL_SetError("Error reading from datastream");
254  case SDL_EFWRITE:
255  return SDL_SetError("Error writing to datastream");
256  case SDL_EFSEEK:
257  return SDL_SetError("Error seeking in datastream");
258  case SDL_UNSUPPORTED:
259  return SDL_SetError("That operation is not supported");
260  default:
261  return SDL_SetError("Unknown SDL error");
262  }
263 }
264 
265 #ifdef TEST_ERROR
266 int
267 main(int argc, char *argv[])
268 {
269  char buffer[BUFSIZ + 1];
270 
271  SDL_SetError("Hi there!");
272  printf("Error 1: %s\n", SDL_GetError());
273  SDL_ClearError();
274  SDL_memset(buffer, '1', BUFSIZ);
275  buffer[BUFSIZ] = 0;
276  SDL_SetError("This is the error: %s (%f)", buffer, 1.0);
277  printf("Error 2: %s\n", SDL_GetError());
278  exit(0);
279 }
280 #endif
281 
282 /* vi: set ts=4 sw=4 expandtab: */
#define SDL_strlcpy
#define SDL_ERRBUFIZE
Definition: SDL_error.c:39
SDL_errorcode
Definition: SDL_error.h:55
double value_f
Definition: SDL_error_c.h:54
int SDL_Error(SDL_errorcode code)
Definition: SDL_error.c:247
static const char * SDL_LookupString(const char *key)
Definition: SDL_error.c:44
SDL_error * SDL_GetErrBuf(void)
Definition: SDL_thread.c:206
GLenum GLsizei len
#define ERR_MAX_STRLEN
Definition: SDL_error_c.h:30
const char * SDL_GetError(void)
Definition: SDL_error.c:229
#define SDL_LogDebug
union SDL_error::@23 args[ERR_MAX_ARGS]
GLenum GLuint GLenum GLsizei const GLchar * buf
#define ERR_MAX_ARGS
Definition: SDL_error_c.h:31
char key[ERR_MAX_STRLEN]
Definition: SDL_error_c.h:43
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
int SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt,...)
Definition: SDL_error.c:53
#define NULL
Definition: begin_code.h:143
static char * SDL_GetErrorMsg(char *errstr, int maxlen)
Definition: SDL_error.c:127
GLuint buffer
char buf[ERR_MAX_STRLEN]
Definition: SDL_error_c.h:55
#define SDL_snprintf
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:90
void * value_ptr
Definition: SDL_error_c.h:49
#define main
Definition: SDL_main.h:104
int value_i
Definition: SDL_error_c.h:53
#define SDL_PRINTF_FORMAT_STRING
Definition: SDL_stdinc.h:252
void SDL_ClearError(void)
Definition: SDL_error.c:237
#define SDL_memset