Atlas - SDL_error.c
Home / ext / SDL2 / src Lines: 3 | Size: 9604 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2018 Sam Lantinga <[email protected]> 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 */ 33static SDL_error SDL_global_error; 34#define SDL_GetErrBuf() (&SDL_global_error) 35#else 36extern SDL_error *SDL_GetErrBuf(void); 37#endif /* SDL_THREADS_DISABLED */ 38 39#define SDL_ERRBUFIZE 1024 40 41/* Private functions */ 42 43static const char * 44SDL_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 52static char *SDL_GetErrorMsg(char *errstr, int maxlen); 53 54int 55SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) 56{ 57 va_list ap; 58 SDL_error *error; 59 60 /* Ignore call if invalid format pointer was passed */ 61 if (fmt == NULL) return -1; 62 63 /* Copy in the key, mark error as valid */ 64 error = SDL_GetErrBuf(); 65 error->error = 1; 66 SDL_strlcpy((char *) error->key, fmt, sizeof(error->key)); 67 68 va_start(ap, fmt); 69 error->argc = 0; 70 while (*fmt) { 71 if (*fmt++ == '%') { 72 while (*fmt == '.' || (*fmt >= '0' && *fmt <= '9')) { 73 ++fmt; 74 } 75 switch (*fmt++) { 76 case 0: /* Malformed format string.. */ 77 --fmt; 78 break; 79 case 'l': 80 switch (*fmt++) { 81 case 0: /* Malformed format string.. */ 82 --fmt; 83 break; 84 case 'i': case 'd': case 'u': 85 error->args[error->argc++].value_l = va_arg(ap, long); 86 break; 87 } 88 break; 89 case 'c': 90 case 'i': 91 case 'd': 92 case 'u': 93 case 'o': 94 case 'x': 95 case 'X': 96 error->args[error->argc++].value_i = va_arg(ap, int); 97 break; 98 case 'f': 99 error->args[error->argc++].value_f = va_arg(ap, double); 100 break; 101 case 'p': 102 error->args[error->argc++].value_ptr = va_arg(ap, void *); 103 break; 104 case 's': 105 { 106 int i = error->argc; 107 const char *str = va_arg(ap, const char *); 108 if (str == NULL) 109 str = "(null)"; 110 SDL_strlcpy((char *) error->args[i].buf, str, 111 ERR_MAX_STRLEN); 112 error->argc++; 113 } 114 break; 115 default: 116 break; 117 } 118 if (error->argc >= ERR_MAX_ARGS) { 119 break; 120 } 121 } 122 } 123 va_end(ap); 124 125 if (SDL_LogGetPriority(SDL_LOG_CATEGORY_ERROR) <= SDL_LOG_PRIORITY_DEBUG) { 126 /* If we are in debug mode, print out an error message 127 * Avoid stomping on the static buffer in GetError, just 128 * in case this is called while processing a ShowMessageBox to 129 * show an error already in that static buffer. 130 */ 131 char errmsg[SDL_ERRBUFIZE]; 132 SDL_GetErrorMsg(errmsg, sizeof(errmsg)); 133 SDL_LogDebug(SDL_LOG_CATEGORY_ERROR, "%s", errmsg); 134 } 135 return -1; 136} 137 138/* Available for backwards compatibility */ 139const char * 140SDL_GetError(void) 141{ 142 static char errmsg[SDL_ERRBUFIZE]; 143 144 return SDL_GetErrorMsg(errmsg, SDL_ERRBUFIZE); 145} 146 147void 148SDL_ClearError(void) 149{ 150 SDL_error *error; 151 152 error = SDL_GetErrBuf(); 153 error->error = 0; 154} 155 156/* Very common errors go here */ 157int 158SDL_Error(SDL_errorcode code) 159{ 160 switch (code) { 161 case SDL_ENOMEM: 162 return SDL_SetError("Out of memory"); 163 case SDL_EFREAD: 164 return SDL_SetError("Error reading from datastream"); 165 case SDL_EFWRITE: 166 return SDL_SetError("Error writing to datastream"); 167 case SDL_EFSEEK: 168 return SDL_SetError("Error seeking in datastream"); 169 case SDL_UNSUPPORTED: 170 return SDL_SetError("That operation is not supported"); 171 default: 172 return SDL_SetError("Unknown SDL error"); 173 } 174} 175 176#ifdef TEST_ERROR 177int 178main(int argc, char *argv[]) 179{ 180 char buffer[BUFSIZ + 1]; 181 182 SDL_SetError("Hi there!"); 183 printf("Error 1: %s\n", SDL_GetError()); 184 SDL_ClearError(); 185 SDL_memset(buffer, '1', BUFSIZ); 186 buffer[BUFSIZ] = 0; 187 SDL_SetError("This is the error: %s (%f)", buffer, 1.0); 188 printf("Error 2: %s\n", SDL_GetError()); 189 exit(0); 190} 191#endif 192 193 194/* keep this at the end of the file so it works with GCC builds that don't 195 support "#pragma GCC diagnostic push" ... we'll just leave the warning 196 disabled after this. */ 197/* this pragma arrived in GCC 4.2 and causes a warning on older GCCs! Sigh. */ 198#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 2)))) 199#pragma GCC diagnostic ignored "-Wformat-nonliteral" 200#endif 201 202/* This function has a bit more overhead than most error functions 203 so that it supports internationalization and thread-safe errors. 204*/ 205static char * 206SDL_GetErrorMsg(char *errstr, int maxlen) 207{ 208 SDL_error *error; 209 210 /* Clear the error string */ 211 *errstr = '\0'; 212 --maxlen; 213 214 /* Get the thread-safe error, and print it out */ 215 error = SDL_GetErrBuf(); 216 if (error->error) { 217 const char *fmt; 218 char *msg = errstr; 219 int len; 220 int argi; 221 222 fmt = SDL_LookupString(error->key); 223 argi = 0; 224 while (*fmt && (maxlen > 0)) { 225 if (*fmt == '%') { 226 char tmp[32], *spot = tmp; 227 *spot++ = *fmt++; 228 while ((*fmt == '.' || (*fmt >= '0' && *fmt <= '9')) 229 && spot < (tmp + SDL_arraysize(tmp) - 2)) { 230 *spot++ = *fmt++; 231 } 232 if (*fmt == 'l') { 233 *spot++ = *fmt++; 234 *spot++ = *fmt++; 235 *spot++ = '\0'; 236 switch (spot[-2]) { 237 case 'i': case 'd': case 'u': 238 len = SDL_snprintf(msg, maxlen, tmp, 239 error->args[argi++].value_l); 240 if (len > 0) { 241 msg += len; 242 maxlen -= len; 243 } 244 break; 245 } 246 continue; 247 } 248 *spot++ = *fmt++; 249 *spot++ = '\0'; 250 switch (spot[-2]) { 251 case '%': 252 *msg++ = '%'; 253 maxlen -= 1; 254 break; 255 case 'c': 256 case 'i': 257 case 'd': 258 case 'u': 259 case 'o': 260 case 'x': 261 case 'X': 262 len = 263 SDL_snprintf(msg, maxlen, tmp, 264 error->args[argi++].value_i); 265 if (len > 0) { 266 msg += len; 267 maxlen -= len; 268 } 269 break; 270 271 case 'f': 272 len = 273 SDL_snprintf(msg, maxlen, tmp, 274 error->args[argi++].value_f); 275 if (len > 0) { 276 msg += len; 277 maxlen -= len; 278 } 279 break; 280 281 case 'p': 282 len = 283 SDL_snprintf(msg, maxlen, tmp, 284 error->args[argi++].value_ptr); 285 if (len > 0) { 286 msg += len; 287 maxlen -= len; 288 } 289 break; 290 291 case 's': 292 len = 293 SDL_snprintf(msg, maxlen, tmp, 294 SDL_LookupString(error->args[argi++]. 295 buf)); 296 if (len > 0) { 297 msg += len; 298 maxlen -= len; 299 } 300 break; 301 302 } 303 } else { 304 *msg++ = *fmt++; 305 maxlen -= 1; 306 } 307 } 308 309 /* slide back if we've overshot the end of our buffer. */ 310 if (maxlen < 0) { 311 msg -= (-maxlen) + 1; 312 } 313 314 *msg = 0; /* NULL terminate the string */ 315 } 316 return (errstr); 317} 318 319/* vi: set ts=4 sw=4 expandtab: */ 320[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.