Atlas - SDL_log.c

Home / ext / SDL2 / src Lines: 12 | Size: 12874 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#if defined(__WIN32__) || defined(__WINRT__) 24#include "core/windows/SDL_windows.h" 25#endif 26 27/* Simple log messages in SDL */ 28 29#include "SDL_error.h" 30#include "SDL_log.h" 31 32#if HAVE_STDIO_H 33#include <stdio.h> 34#endif 35 36#if defined(__ANDROID__) 37#include <android/log.h> 38#endif 39 40#define DEFAULT_PRIORITY SDL_LOG_PRIORITY_CRITICAL 41#define DEFAULT_ASSERT_PRIORITY SDL_LOG_PRIORITY_WARN 42#define DEFAULT_APPLICATION_PRIORITY SDL_LOG_PRIORITY_INFO 43#define DEFAULT_TEST_PRIORITY SDL_LOG_PRIORITY_VERBOSE 44 45typedef struct SDL_LogLevel 46{ 47 int category; 48 SDL_LogPriority priority; 49 struct SDL_LogLevel *next; 50} SDL_LogLevel; 51 52/* The default log output function */ 53static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority, const char *message); 54 55static SDL_LogLevel *SDL_loglevels; 56static SDL_LogPriority SDL_default_priority = DEFAULT_PRIORITY; 57static SDL_LogPriority SDL_assert_priority = DEFAULT_ASSERT_PRIORITY; 58static SDL_LogPriority SDL_application_priority = DEFAULT_APPLICATION_PRIORITY; 59static SDL_LogPriority SDL_test_priority = DEFAULT_TEST_PRIORITY; 60static SDL_LogOutputFunction SDL_log_function = SDL_LogOutput; 61static void *SDL_log_userdata = NULL; 62 63static const char *SDL_priority_prefixes[SDL_NUM_LOG_PRIORITIES] = { 64 NULL, 65 "VERBOSE", 66 "DEBUG", 67 "INFO", 68 "WARN", 69 "ERROR", 70 "CRITICAL" 71}; 72 73#ifdef __ANDROID__ 74static const char *SDL_category_prefixes[SDL_LOG_CATEGORY_RESERVED1] = { 75 "APP", 76 "ERROR", 77 "SYSTEM", 78 "AUDIO", 79 "VIDEO", 80 "RENDER", 81 "INPUT" 82}; 83 84static int SDL_android_priority[SDL_NUM_LOG_PRIORITIES] = { 85 ANDROID_LOG_UNKNOWN, 86 ANDROID_LOG_VERBOSE, 87 ANDROID_LOG_DEBUG, 88 ANDROID_LOG_INFO, 89 ANDROID_LOG_WARN, 90 ANDROID_LOG_ERROR, 91 ANDROID_LOG_FATAL 92}; 93#endif /* __ANDROID__ */ 94 95 96void 97SDL_LogSetAllPriority(SDL_LogPriority priority) 98{ 99 SDL_LogLevel *entry; 100 101 for (entry = SDL_loglevels; entry; entry = entry->next) { 102 entry->priority = priority; 103 } 104 SDL_default_priority = priority; 105 SDL_assert_priority = priority; 106 SDL_application_priority = priority; 107} 108 109void 110SDL_LogSetPriority(int category, SDL_LogPriority priority) 111{ 112 SDL_LogLevel *entry; 113 114 for (entry = SDL_loglevels; entry; entry = entry->next) { 115 if (entry->category == category) { 116 entry->priority = priority; 117 return; 118 } 119 } 120 121 /* Create a new entry */ 122 entry = (SDL_LogLevel *)SDL_malloc(sizeof(*entry)); 123 if (entry) { 124 entry->category = category; 125 entry->priority = priority; 126 entry->next = SDL_loglevels; 127 SDL_loglevels = entry; 128 } 129} 130 131SDL_LogPriority 132SDL_LogGetPriority(int category) 133{ 134 SDL_LogLevel *entry; 135 136 for (entry = SDL_loglevels; entry; entry = entry->next) { 137 if (entry->category == category) { 138 return entry->priority; 139 } 140 } 141 142 if (category == SDL_LOG_CATEGORY_TEST) { 143 return SDL_test_priority; 144 } else if (category == SDL_LOG_CATEGORY_APPLICATION) { 145 return SDL_application_priority; 146 } else if (category == SDL_LOG_CATEGORY_ASSERT) { 147 return SDL_assert_priority; 148 } else { 149 return SDL_default_priority; 150 } 151} 152 153void 154SDL_LogResetPriorities(void) 155{ 156 SDL_LogLevel *entry; 157 158 while (SDL_loglevels) { 159 entry = SDL_loglevels; 160 SDL_loglevels = entry->next; 161 SDL_free(entry); 162 } 163 164 SDL_default_priority = DEFAULT_PRIORITY; 165 SDL_assert_priority = DEFAULT_ASSERT_PRIORITY; 166 SDL_application_priority = DEFAULT_APPLICATION_PRIORITY; 167 SDL_test_priority = DEFAULT_TEST_PRIORITY; 168} 169 170void 171SDL_Log(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) 172{ 173 va_list ap; 174 175 va_start(ap, fmt); 176 SDL_LogMessageV(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, fmt, ap); 177 va_end(ap); 178} 179 180void 181SDL_LogVerbose(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) 182{ 183 va_list ap; 184 185 va_start(ap, fmt); 186 SDL_LogMessageV(category, SDL_LOG_PRIORITY_VERBOSE, fmt, ap); 187 va_end(ap); 188} 189 190void 191SDL_LogDebug(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) 192{ 193 va_list ap; 194 195 va_start(ap, fmt); 196 SDL_LogMessageV(category, SDL_LOG_PRIORITY_DEBUG, fmt, ap); 197 va_end(ap); 198} 199 200void 201SDL_LogInfo(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) 202{ 203 va_list ap; 204 205 va_start(ap, fmt); 206 SDL_LogMessageV(category, SDL_LOG_PRIORITY_INFO, fmt, ap); 207 va_end(ap); 208} 209 210void 211SDL_LogWarn(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) 212{ 213 va_list ap; 214 215 va_start(ap, fmt); 216 SDL_LogMessageV(category, SDL_LOG_PRIORITY_WARN, fmt, ap); 217 va_end(ap); 218} 219 220void 221SDL_LogError(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) 222{ 223 va_list ap; 224 225 va_start(ap, fmt); 226 SDL_LogMessageV(category, SDL_LOG_PRIORITY_ERROR, fmt, ap); 227 va_end(ap); 228} 229 230void 231SDL_LogCritical(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) 232{ 233 va_list ap; 234 235 va_start(ap, fmt); 236 SDL_LogMessageV(category, SDL_LOG_PRIORITY_CRITICAL, fmt, ap); 237 va_end(ap); 238} 239 240void 241SDL_LogMessage(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) 242{ 243 va_list ap; 244 245 va_start(ap, fmt); 246 SDL_LogMessageV(category, priority, fmt, ap); 247 va_end(ap); 248} 249 250#ifdef __ANDROID__ 251static const char * 252GetCategoryPrefix(int category) 253{ 254 if (category < SDL_LOG_CATEGORY_RESERVED1) { 255 return SDL_category_prefixes[category]; 256 } 257 if (category < SDL_LOG_CATEGORY_CUSTOM) { 258 return "RESERVED"; 259 } 260 return "CUSTOM"; 261} 262#endif /* __ANDROID__ */ 263 264void 265SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list ap) 266{ 267 char *message; 268 size_t len; 269 270 /* Nothing to do if we don't have an output function */ 271 if (!SDL_log_function) { 272 return; 273 } 274 275 /* Make sure we don't exceed array bounds */ 276 if ((int)priority < 0 || priority >= SDL_NUM_LOG_PRIORITIES) { 277 return; 278 } 279 280 /* See if we want to do anything with this message */ 281 if (priority < SDL_LogGetPriority(category)) { 282 return; 283 } 284 285 message = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE); 286 if (!message) { 287 return; 288 } 289 290 SDL_vsnprintf(message, SDL_MAX_LOG_MESSAGE, fmt, ap); 291 292 /* Chop off final endline. */ 293 len = SDL_strlen(message); 294 if ((len > 0) && (message[len-1] == '\n')) { 295 message[--len] = '\0'; 296 if ((len > 0) && (message[len-1] == '\r')) { /* catch "\r\n", too. */ 297 message[--len] = '\0'; 298 } 299 } 300 301 SDL_log_function(SDL_log_userdata, category, priority, message); 302 SDL_stack_free(message); 303} 304 305#if defined(__WIN32__) && !defined(HAVE_STDIO_H) && !defined(__WINRT__) 306/* Flag tracking the attachment of the console: 0=unattached, 1=attached to a console, 2=attached to a file, -1=error */ 307static int consoleAttached = 0; 308 309/* Handle to stderr output of console. */ 310static HANDLE stderrHandle = NULL; 311#endif 312 313static void SDLCALL 314SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority, 315 const char *message) 316{ 317#if defined(__WIN32__) || defined(__WINRT__) 318 /* Way too many allocations here, urgh */ 319 /* Note: One can't call SDL_SetError here, since that function itself logs. */ 320 { 321 char *output; 322 size_t length; 323 LPTSTR tstr; 324 325#if !defined(HAVE_STDIO_H) && !defined(__WINRT__) 326 BOOL attachResult; 327 DWORD attachError; 328 unsigned long charsWritten; 329 DWORD consoleMode; 330 331 /* Maybe attach console and get stderr handle */ 332 if (consoleAttached == 0) { 333 attachResult = AttachConsole(ATTACH_PARENT_PROCESS); 334 if (!attachResult) { 335 attachError = GetLastError(); 336 if (attachError == ERROR_INVALID_HANDLE) { 337 /* This is expected when running from Visual Studio */ 338 /*OutputDebugString(TEXT("Parent process has no console\r\n"));*/ 339 consoleAttached = -1; 340 } else if (attachError == ERROR_GEN_FAILURE) { 341 OutputDebugString(TEXT("Could not attach to console of parent process\r\n")); 342 consoleAttached = -1; 343 } else if (attachError == ERROR_ACCESS_DENIED) { 344 /* Already attached */ 345 consoleAttached = 1; 346 } else { 347 OutputDebugString(TEXT("Error attaching console\r\n")); 348 consoleAttached = -1; 349 } 350 } else { 351 /* Newly attached */ 352 consoleAttached = 1; 353 } 354 355 if (consoleAttached == 1) { 356 stderrHandle = GetStdHandle(STD_ERROR_HANDLE); 357 358 if (GetConsoleMode(stderrHandle, &consoleMode) == 0) { 359 /* WriteConsole fails if the output is redirected to a file. Must use WriteFile instead. */ 360 consoleAttached = 2; 361 } 362 } 363 } 364#endif /* !defined(HAVE_STDIO_H) && !defined(__WINRT__) */ 365 366 length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1 + 1 + 1; 367 output = SDL_stack_alloc(char, length); 368 SDL_snprintf(output, length, "%s: %s\r\n", SDL_priority_prefixes[priority], message); 369 tstr = WIN_UTF8ToString(output); 370 371 /* Output to debugger */ 372 OutputDebugString(tstr); 373 374#if !defined(HAVE_STDIO_H) && !defined(__WINRT__) 375 /* Screen output to stderr, if console was attached. */ 376 if (consoleAttached == 1) { 377 if (!WriteConsole(stderrHandle, tstr, lstrlen(tstr), &charsWritten, NULL)) { 378 OutputDebugString(TEXT("Error calling WriteConsole\r\n")); 379 if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY) { 380 OutputDebugString(TEXT("Insufficient heap memory to write message\r\n")); 381 } 382 } 383 384 } else if (consoleAttached == 2) { 385 if (!WriteFile(stderrHandle, output, lstrlenA(output), &charsWritten, NULL)) { 386 OutputDebugString(TEXT("Error calling WriteFile\r\n")); 387 } 388 } 389#endif /* !defined(HAVE_STDIO_H) && !defined(__WINRT__) */ 390 391 SDL_free(tstr); 392 SDL_stack_free(output); 393 } 394#elif defined(__ANDROID__) 395 { 396 char tag[32]; 397 398 SDL_snprintf(tag, SDL_arraysize(tag), "SDL/%s", GetCategoryPrefix(category)); 399 __android_log_write(SDL_android_priority[priority], tag, message); 400 } 401#elif defined(__APPLE__) && defined(SDL_VIDEO_DRIVER_COCOA) 402 /* Technically we don't need SDL_VIDEO_DRIVER_COCOA, but that's where this function is defined for now. 403 */ 404 extern void SDL_NSLog(const char *text); 405 { 406 char *text; 407 408 text = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE); 409 if (text) { 410 SDL_snprintf(text, SDL_MAX_LOG_MESSAGE, "%s: %s", SDL_priority_prefixes[priority], message); 411 SDL_NSLog(text); 412 SDL_stack_free(text); 413 return; 414 } 415 } 416#elif defined(__PSP__) 417 { 418 FILE* pFile; 419 pFile = fopen ("SDL_Log.txt", "a"); 420 fprintf(pFile, "%s: %s\n", SDL_priority_prefixes[priority], message); 421 fclose (pFile); 422 } 423#endif 424#if HAVE_STDIO_H 425 fprintf(stderr, "%s: %s\n", SDL_priority_prefixes[priority], message); 426#if __NACL__ 427 fflush(stderr); 428#endif 429#endif 430} 431 432void 433SDL_LogGetOutputFunction(SDL_LogOutputFunction *callback, void **userdata) 434{ 435 if (callback) { 436 *callback = SDL_log_function; 437 } 438 if (userdata) { 439 *userdata = SDL_log_userdata; 440 } 441} 442 443void 444SDL_LogSetOutputFunction(SDL_LogOutputFunction callback, void *userdata) 445{ 446 SDL_log_function = callback; 447 SDL_log_userdata = userdata; 448} 449 450/* vi: set ts=4 sw=4 expandtab: */ 451
[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.