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 /* This function has a bit more overhead than most error functions
120  so that it supports internationalization and thread-safe errors.
121 */
122 static char *
123 SDL_GetErrorMsg(char *errstr, int maxlen)
124 {
125  SDL_error *error;
126 
127  /* Clear the error string */
128  *errstr = '\0';
129  --maxlen;
130 
131  /* Get the thread-safe error, and print it out */
132  error = SDL_GetErrBuf();
133  if (error->error) {
134  const char *fmt;
135  char *msg = errstr;
136  int len;
137  int argi;
138 
139  fmt = SDL_LookupString(error->key);
140  argi = 0;
141  while (*fmt && (maxlen > 0)) {
142  if (*fmt == '%') {
143  char tmp[32], *spot = tmp;
144  *spot++ = *fmt++;
145  while ((*fmt == '.' || (*fmt >= '0' && *fmt <= '9'))
146  && spot < (tmp + SDL_arraysize(tmp) - 2)) {
147  *spot++ = *fmt++;
148  }
149  *spot++ = *fmt++;
150  *spot++ = '\0';
151  switch (spot[-2]) {
152  case '%':
153  *msg++ = '%';
154  maxlen -= 1;
155  break;
156  case 'c':
157  case 'i':
158  case 'd':
159  case 'u':
160  case 'o':
161  case 'x':
162  case 'X':
163  len =
164  SDL_snprintf(msg, maxlen, tmp,
165  error->args[argi++].value_i);
166  if (len > 0) {
167  msg += len;
168  maxlen -= len;
169  }
170  break;
171 
172  case 'f':
173  len =
174  SDL_snprintf(msg, maxlen, tmp,
175  error->args[argi++].value_f);
176  if (len > 0) {
177  msg += len;
178  maxlen -= len;
179  }
180  break;
181 
182  case 'p':
183  len =
184  SDL_snprintf(msg, maxlen, tmp,
185  error->args[argi++].value_ptr);
186  if (len > 0) {
187  msg += len;
188  maxlen -= len;
189  }
190  break;
191 
192  case 's':
193  len =
194  SDL_snprintf(msg, maxlen, tmp,
195  SDL_LookupString(error->args[argi++].
196  buf));
197  if (len > 0) {
198  msg += len;
199  maxlen -= len;
200  }
201  break;
202 
203  }
204  } else {
205  *msg++ = *fmt++;
206  maxlen -= 1;
207  }
208  }
209 
210  /* slide back if we've overshot the end of our buffer. */
211  if (maxlen < 0) {
212  msg -= (-maxlen) + 1;
213  }
214 
215  *msg = 0; /* NULL terminate the string */
216  }
217  return (errstr);
218 }
219 
220 /* Available for backwards compatibility */
221 const char *
223 {
224  static char errmsg[SDL_ERRBUFIZE];
225 
226  return SDL_GetErrorMsg(errmsg, SDL_ERRBUFIZE);
227 }
228 
229 void
231 {
232  SDL_error *error;
233 
234  error = SDL_GetErrBuf();
235  error->error = 0;
236 }
237 
238 /* Very common errors go here */
239 int
241 {
242  switch (code) {
243  case SDL_ENOMEM:
244  return SDL_SetError("Out of memory");
245  case SDL_EFREAD:
246  return SDL_SetError("Error reading from datastream");
247  case SDL_EFWRITE:
248  return SDL_SetError("Error writing to datastream");
249  case SDL_EFSEEK:
250  return SDL_SetError("Error seeking in datastream");
251  case SDL_UNSUPPORTED:
252  return SDL_SetError("That operation is not supported");
253  default:
254  return SDL_SetError("Unknown SDL error");
255  }
256 }
257 
258 #ifdef TEST_ERROR
259 int
260 main(int argc, char *argv[])
261 {
262  char buffer[BUFSIZ + 1];
263 
264  SDL_SetError("Hi there!");
265  printf("Error 1: %s\n", SDL_GetError());
266  SDL_ClearError();
267  SDL_memset(buffer, '1', BUFSIZ);
268  buffer[BUFSIZ] = 0;
269  SDL_SetError("This is the error: %s (%f)", buffer, 1.0);
270  printf("Error 2: %s\n", SDL_GetError());
271  exit(0);
272 }
273 #endif
274 
275 /* 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:240
static const char * SDL_LookupString(const char *key)
Definition: SDL_error.c:44
SDL_error * SDL_GetErrBuf(void)
Definition: SDL_thread.c:205
GLenum GLsizei len
#define ERR_MAX_STRLEN
Definition: SDL_error_c.h:30
const char * SDL_GetError(void)
Definition: SDL_error.c:222
#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:42
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:123
GLuint buffer
char buf[ERR_MAX_STRLEN]
Definition: SDL_error_c.h:55
#define SDL_snprintf
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:93
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:248
void SDL_ClearError(void)
Definition: SDL_error.c:230
#define SDL_memset