2 Simple DirectMedia Layer
3 Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
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.
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:
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.
21 #include "./SDL_internal.h"
23 /* Simple error handling in SDL */
26 #include "SDL_error.h"
27 #include "SDL_error_c.h"
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)
36 extern SDL_error *SDL_GetErrBuf(void);
37 #endif /* SDL_THREADS_DISABLED */
39 #define SDL_ERRBUFIZE 1024
41 /* Private functions */
44 SDL_LookupString(const char *key)
46 /* FIXME: Add code to lookup key in language string hash-table */
50 /* Public functions */
52 static char *SDL_GetErrorMsg(char *errstr, int maxlen);
55 SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
60 /* Ignore call if invalid format pointer was passed */
61 if (fmt == NULL) return -1;
63 /* Copy in the key, mark error as valid */
64 error = SDL_GetErrBuf();
66 SDL_strlcpy((char *) error->key, fmt, sizeof(error->key));
72 while (*fmt == '.' || (*fmt >= '0' && *fmt <= '9')) {
76 case 0: /* Malformed format string.. */
86 error->args[error->argc++].value_i = va_arg(ap, int);
89 error->args[error->argc++].value_f = va_arg(ap, double);
92 error->args[error->argc++].value_ptr = va_arg(ap, void *);
97 const char *str = va_arg(ap, const char *);
100 SDL_strlcpy((char *) error->args[i].buf, str,
108 if (error->argc >= ERR_MAX_ARGS) {
115 if (SDL_LogGetPriority(SDL_LOG_CATEGORY_ERROR) <= SDL_LOG_PRIORITY_DEBUG) {
116 /* If we are in debug mode, print out an error message
117 * Avoid stomping on the static buffer in GetError, just
118 * in case this is called while processing a ShowMessageBox to
119 * show an error already in that static buffer.
121 char errmsg[SDL_ERRBUFIZE];
122 SDL_GetErrorMsg(errmsg, sizeof(errmsg));
123 SDL_LogDebug(SDL_LOG_CATEGORY_ERROR, "%s", errmsg);
128 /* Available for backwards compatibility */
132 static char errmsg[SDL_ERRBUFIZE];
134 return SDL_GetErrorMsg(errmsg, SDL_ERRBUFIZE);
142 error = SDL_GetErrBuf();
146 /* Very common errors go here */
148 SDL_Error(SDL_errorcode code)
152 return SDL_SetError("Out of memory");
154 return SDL_SetError("Error reading from datastream");
156 return SDL_SetError("Error writing to datastream");
158 return SDL_SetError("Error seeking in datastream");
159 case SDL_UNSUPPORTED:
160 return SDL_SetError("That operation is not supported");
162 return SDL_SetError("Unknown SDL error");
168 main(int argc, char *argv[])
170 char buffer[BUFSIZ + 1];
172 SDL_SetError("Hi there!");
173 printf("Error 1: %s\n", SDL_GetError());
175 SDL_memset(buffer, '1', BUFSIZ);
177 SDL_SetError("This is the error: %s (%f)", buffer, 1.0);
178 printf("Error 2: %s\n", SDL_GetError());
184 /* keep this at the end of the file so it works with GCC builds that don't
185 support "#pragma GCC diagnostic push" ... we'll just leave the warning
186 disabled after this. */
187 /* this pragma arrived in GCC 4.2 and causes a warning on older GCCs! Sigh. */
188 #if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 2))))
189 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
192 /* This function has a bit more overhead than most error functions
193 so that it supports internationalization and thread-safe errors.
196 SDL_GetErrorMsg(char *errstr, int maxlen)
200 /* Clear the error string */
204 /* Get the thread-safe error, and print it out */
205 error = SDL_GetErrBuf();
212 fmt = SDL_LookupString(error->key);
214 while (*fmt && (maxlen > 0)) {
216 char tmp[32], *spot = tmp;
218 while ((*fmt == '.' || (*fmt >= '0' && *fmt <= '9'))
219 && spot < (tmp + SDL_arraysize(tmp) - 2)) {
237 SDL_snprintf(msg, maxlen, tmp,
238 error->args[argi++].value_i);
247 SDL_snprintf(msg, maxlen, tmp,
248 error->args[argi++].value_f);
257 SDL_snprintf(msg, maxlen, tmp,
258 error->args[argi++].value_ptr);
267 SDL_snprintf(msg, maxlen, tmp,
268 SDL_LookupString(error->args[argi++].
283 /* slide back if we've overshot the end of our buffer. */
285 msg -= (-maxlen) + 1;
288 *msg = 0; /* NULL terminate the string */
293 /* vi: set ts=4 sw=4 expandtab: */