src/SDL_log.c
changeset 8582 c3e9a2b93517
parent 8536 a2be4a225f91
child 8583 fb2933ca805f
     1.1 --- a/src/SDL_log.c	Tue Mar 04 19:49:11 2014 -0500
     1.2 +++ b/src/SDL_log.c	Sun Mar 09 11:06:11 2014 -0700
     1.3 @@ -1,439 +1,439 @@
     1.4 -/*
     1.5 -  Simple DirectMedia Layer
     1.6 -  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
     1.7 -
     1.8 -  This software is provided 'as-is', without any express or implied
     1.9 -  warranty.  In no event will the authors be held liable for any damages
    1.10 -  arising from the use of this software.
    1.11 -
    1.12 -  Permission is granted to anyone to use this software for any purpose,
    1.13 -  including commercial applications, and to alter it and redistribute it
    1.14 -  freely, subject to the following restrictions:
    1.15 -
    1.16 -  1. The origin of this software must not be misrepresented; you must not
    1.17 -     claim that you wrote the original software. If you use this software
    1.18 -     in a product, an acknowledgment in the product documentation would be
    1.19 -     appreciated but is not required.
    1.20 -  2. Altered source versions must be plainly marked as such, and must not be
    1.21 -     misrepresented as being the original software.
    1.22 -  3. This notice may not be removed or altered from any source distribution.
    1.23 -*/
    1.24 -#include "SDL_config.h"
    1.25 -
    1.26 -#if defined(__WIN32__) || defined(__WINRT__)
    1.27 -#include "core/windows/SDL_windows.h"
    1.28 -#endif
    1.29 -
    1.30 -/* Simple log messages in SDL */
    1.31 -
    1.32 -#include "SDL_log.h"
    1.33 -
    1.34 -#if HAVE_STDIO_H
    1.35 -#include <stdio.h>
    1.36 -#endif
    1.37 -
    1.38 -#if defined(__ANDROID__)
    1.39 -#include <android/log.h>
    1.40 -#endif
    1.41 -
    1.42 -#define DEFAULT_PRIORITY                SDL_LOG_PRIORITY_CRITICAL
    1.43 -#define DEFAULT_ASSERT_PRIORITY         SDL_LOG_PRIORITY_WARN
    1.44 -#define DEFAULT_APPLICATION_PRIORITY    SDL_LOG_PRIORITY_INFO
    1.45 -#define DEFAULT_TEST_PRIORITY           SDL_LOG_PRIORITY_VERBOSE
    1.46 -
    1.47 -/* Forward definition of error function */
    1.48 -extern int SDL_SetError(const char *fmt, ...);
    1.49 -
    1.50 -typedef struct SDL_LogLevel
    1.51 -{
    1.52 -    int category;
    1.53 -    SDL_LogPriority priority;
    1.54 -    struct SDL_LogLevel *next;
    1.55 -} SDL_LogLevel;
    1.56 -
    1.57 -/* The default log output function */
    1.58 -static void SDL_LogOutput(void *userdata,
    1.59 -                          int category, SDL_LogPriority priority,
    1.60 -                          const char *message);
    1.61 -
    1.62 -static SDL_LogLevel *SDL_loglevels;
    1.63 -static SDL_LogPriority SDL_default_priority = DEFAULT_PRIORITY;
    1.64 -static SDL_LogPriority SDL_assert_priority = DEFAULT_ASSERT_PRIORITY;
    1.65 -static SDL_LogPriority SDL_application_priority = DEFAULT_APPLICATION_PRIORITY;
    1.66 -static SDL_LogPriority SDL_test_priority = DEFAULT_TEST_PRIORITY;
    1.67 -static SDL_LogOutputFunction SDL_log_function = SDL_LogOutput;
    1.68 -static void *SDL_log_userdata = NULL;
    1.69 -
    1.70 -static const char *SDL_priority_prefixes[SDL_NUM_LOG_PRIORITIES] = {
    1.71 -    NULL,
    1.72 -    "VERBOSE",
    1.73 -    "DEBUG",
    1.74 -    "INFO",
    1.75 -    "WARN",
    1.76 -    "ERROR",
    1.77 -    "CRITICAL"
    1.78 -};
    1.79 -
    1.80 -#ifdef __ANDROID__
    1.81 -static const char *SDL_category_prefixes[SDL_LOG_CATEGORY_RESERVED1] = {
    1.82 -    "APP",
    1.83 -    "ERROR",
    1.84 -    "SYSTEM",
    1.85 -    "AUDIO",
    1.86 -    "VIDEO",
    1.87 -    "RENDER",
    1.88 -    "INPUT"
    1.89 -};
    1.90 -
    1.91 -static int SDL_android_priority[SDL_NUM_LOG_PRIORITIES] = {
    1.92 -    ANDROID_LOG_UNKNOWN,
    1.93 -    ANDROID_LOG_VERBOSE,
    1.94 -    ANDROID_LOG_DEBUG,
    1.95 -    ANDROID_LOG_INFO,
    1.96 -    ANDROID_LOG_WARN,
    1.97 -    ANDROID_LOG_ERROR,
    1.98 -    ANDROID_LOG_FATAL
    1.99 -};
   1.100 -#endif /* __ANDROID__ */
   1.101 -
   1.102 -
   1.103 -void
   1.104 -SDL_LogSetAllPriority(SDL_LogPriority priority)
   1.105 -{
   1.106 -    SDL_LogLevel *entry;
   1.107 -
   1.108 -    for (entry = SDL_loglevels; entry; entry = entry->next) {
   1.109 -        entry->priority = priority;
   1.110 -    }
   1.111 -    SDL_default_priority = priority;
   1.112 -    SDL_assert_priority = priority;
   1.113 -    SDL_application_priority = priority;
   1.114 -}
   1.115 -
   1.116 -void
   1.117 -SDL_LogSetPriority(int category, SDL_LogPriority priority)
   1.118 -{
   1.119 -    SDL_LogLevel *entry;
   1.120 -
   1.121 -    for (entry = SDL_loglevels; entry; entry = entry->next) {
   1.122 -        if (entry->category == category) {
   1.123 -            entry->priority = priority;
   1.124 -            return;
   1.125 -        }
   1.126 -    }
   1.127 -
   1.128 -    /* Create a new entry */
   1.129 -    entry = (SDL_LogLevel *)SDL_malloc(sizeof(*entry));
   1.130 -    if (entry) {
   1.131 -        entry->category = category;
   1.132 -        entry->priority = priority;
   1.133 -        entry->next = SDL_loglevels;
   1.134 -        SDL_loglevels = entry;
   1.135 -    }
   1.136 -}
   1.137 -
   1.138 -SDL_LogPriority
   1.139 -SDL_LogGetPriority(int category)
   1.140 -{
   1.141 -    SDL_LogLevel *entry;
   1.142 -
   1.143 -    for (entry = SDL_loglevels; entry; entry = entry->next) {
   1.144 -        if (entry->category == category) {
   1.145 -            return entry->priority;
   1.146 -        }
   1.147 -    }
   1.148 -
   1.149 -    if (category == SDL_LOG_CATEGORY_TEST) {
   1.150 -        return SDL_test_priority;
   1.151 -    } else if (category == SDL_LOG_CATEGORY_APPLICATION) {
   1.152 -        return SDL_application_priority;
   1.153 -    } else if (category == SDL_LOG_CATEGORY_ASSERT) {
   1.154 -        return SDL_assert_priority;
   1.155 -    } else {
   1.156 -        return SDL_default_priority;
   1.157 -    }
   1.158 -}
   1.159 -
   1.160 -void
   1.161 -SDL_LogResetPriorities(void)
   1.162 -{
   1.163 -    SDL_LogLevel *entry;
   1.164 -
   1.165 -    while (SDL_loglevels) {
   1.166 -        entry = SDL_loglevels;
   1.167 -        SDL_loglevels = entry->next;
   1.168 -        SDL_free(entry);
   1.169 -    }
   1.170 -
   1.171 -    SDL_default_priority = DEFAULT_PRIORITY;
   1.172 -    SDL_assert_priority = DEFAULT_ASSERT_PRIORITY;
   1.173 -    SDL_application_priority = DEFAULT_APPLICATION_PRIORITY;
   1.174 -    SDL_test_priority = DEFAULT_TEST_PRIORITY;
   1.175 -}
   1.176 -
   1.177 -void
   1.178 -SDL_Log(const char *fmt, ...)
   1.179 -{
   1.180 -    va_list ap;
   1.181 -
   1.182 -    va_start(ap, fmt);
   1.183 -    SDL_LogMessageV(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, fmt, ap);
   1.184 -    va_end(ap);
   1.185 -}
   1.186 -
   1.187 -void
   1.188 -SDL_LogVerbose(int category, const char *fmt, ...)
   1.189 -{
   1.190 -    va_list ap;
   1.191 -
   1.192 -    va_start(ap, fmt);
   1.193 -    SDL_LogMessageV(category, SDL_LOG_PRIORITY_VERBOSE, fmt, ap);
   1.194 -    va_end(ap);
   1.195 -}
   1.196 -
   1.197 -void
   1.198 -SDL_LogDebug(int category, const char *fmt, ...)
   1.199 -{
   1.200 -    va_list ap;
   1.201 -
   1.202 -    va_start(ap, fmt);
   1.203 -    SDL_LogMessageV(category, SDL_LOG_PRIORITY_DEBUG, fmt, ap);
   1.204 -    va_end(ap);
   1.205 -}
   1.206 -
   1.207 -void
   1.208 -SDL_LogInfo(int category, const char *fmt, ...)
   1.209 -{
   1.210 -    va_list ap;
   1.211 -
   1.212 -    va_start(ap, fmt);
   1.213 -    SDL_LogMessageV(category, SDL_LOG_PRIORITY_INFO, fmt, ap);
   1.214 -    va_end(ap);
   1.215 -}
   1.216 -
   1.217 -void
   1.218 -SDL_LogWarn(int category, const char *fmt, ...)
   1.219 -{
   1.220 -    va_list ap;
   1.221 -
   1.222 -    va_start(ap, fmt);
   1.223 -    SDL_LogMessageV(category, SDL_LOG_PRIORITY_WARN, fmt, ap);
   1.224 -    va_end(ap);
   1.225 -}
   1.226 -
   1.227 -void
   1.228 -SDL_LogError(int category, const char *fmt, ...)
   1.229 -{
   1.230 -    va_list ap;
   1.231 -
   1.232 -    va_start(ap, fmt);
   1.233 -    SDL_LogMessageV(category, SDL_LOG_PRIORITY_ERROR, fmt, ap);
   1.234 -    va_end(ap);
   1.235 -}
   1.236 -
   1.237 -void
   1.238 -SDL_LogCritical(int category, const char *fmt, ...)
   1.239 -{
   1.240 -    va_list ap;
   1.241 -
   1.242 -    va_start(ap, fmt);
   1.243 -    SDL_LogMessageV(category, SDL_LOG_PRIORITY_CRITICAL, fmt, ap);
   1.244 -    va_end(ap);
   1.245 -}
   1.246 -
   1.247 -void
   1.248 -SDL_LogMessage(int category, SDL_LogPriority priority, const char *fmt, ...)
   1.249 -{
   1.250 -    va_list ap;
   1.251 -
   1.252 -    va_start(ap, fmt);
   1.253 -    SDL_LogMessageV(category, priority, fmt, ap);
   1.254 -    va_end(ap);
   1.255 -}
   1.256 -
   1.257 -#ifdef __ANDROID__
   1.258 -static const char *
   1.259 -GetCategoryPrefix(int category)
   1.260 -{
   1.261 -    if (category < SDL_LOG_CATEGORY_RESERVED1) {
   1.262 -        return SDL_category_prefixes[category];
   1.263 -    }
   1.264 -    if (category < SDL_LOG_CATEGORY_CUSTOM) {
   1.265 -        return "RESERVED";
   1.266 -    }
   1.267 -    return "CUSTOM";
   1.268 -}
   1.269 -#endif /* __ANDROID__ */
   1.270 -
   1.271 -void
   1.272 -SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list ap)
   1.273 -{
   1.274 -    char *message;
   1.275 -    size_t len;
   1.276 -
   1.277 -    /* Nothing to do if we don't have an output function */
   1.278 -    if (!SDL_log_function) {
   1.279 -        return;
   1.280 -    }
   1.281 -
   1.282 -    /* Make sure we don't exceed array bounds */
   1.283 -    if ((int)priority < 0 || priority >= SDL_NUM_LOG_PRIORITIES) {
   1.284 -        return;
   1.285 -    }
   1.286 -
   1.287 -    /* See if we want to do anything with this message */
   1.288 -    if (priority < SDL_LogGetPriority(category)) {
   1.289 -        return;
   1.290 -    }
   1.291 -
   1.292 -    message = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE);
   1.293 -    if (!message) {
   1.294 -        return;
   1.295 -    }
   1.296 -
   1.297 -    SDL_vsnprintf(message, SDL_MAX_LOG_MESSAGE, fmt, ap);
   1.298 -
   1.299 -    /* Chop off final endline. */
   1.300 -    len = SDL_strlen(message);
   1.301 -    if ((len > 0) && (message[len-1] == '\n')) {
   1.302 -        message[--len] = '\0';
   1.303 -        if ((len > 0) && (message[len-1] == '\r')) {  /* catch "\r\n", too. */
   1.304 -            message[--len] = '\0';
   1.305 -        }
   1.306 -    }
   1.307 -
   1.308 -    SDL_log_function(SDL_log_userdata, category, priority, message);
   1.309 -    SDL_stack_free(message);
   1.310 -}
   1.311 -
   1.312 -#if defined(__WIN32__)
   1.313 -/* Flag tracking the attachment of the console: 0=unattached, 1=attached, -1=error */
   1.314 -static int consoleAttached = 0;
   1.315 -
   1.316 -/* Handle to stderr output of console. */
   1.317 -static HANDLE stderrHandle = NULL;
   1.318 -#endif
   1.319 -
   1.320 -static void
   1.321 -SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
   1.322 -              const char *message)
   1.323 -{
   1.324 -#if defined(__WIN32__) || defined(__WINRT__)
   1.325 -    /* Way too many allocations here, urgh */
   1.326 -    /* Note: One can't call SDL_SetError here, since that function itself logs. */
   1.327 -    {
   1.328 -        char *output;
   1.329 -        size_t length;
   1.330 -        LPTSTR tstr;
   1.331 -
   1.332 -#ifndef __WINRT__
   1.333 -        BOOL attachResult;
   1.334 -        DWORD attachError;
   1.335 -        unsigned long charsWritten; 
   1.336 -
   1.337 -        /* Maybe attach console and get stderr handle */
   1.338 -        if (consoleAttached == 0) {
   1.339 -            attachResult = AttachConsole(ATTACH_PARENT_PROCESS);
   1.340 -            if (!attachResult) {
   1.341 -                    attachError = GetLastError();
   1.342 -                    if (attachError == ERROR_INVALID_HANDLE) {
   1.343 -                        OutputDebugString(TEXT("Parent process has no console\r\n"));
   1.344 -                        consoleAttached = -1;
   1.345 -                    } else if (attachError == ERROR_GEN_FAILURE) {
   1.346 -                         OutputDebugString(TEXT("Could not attach to console of parent process\r\n"));
   1.347 -                         consoleAttached = -1;
   1.348 -                    } else if (attachError == ERROR_ACCESS_DENIED) {  
   1.349 -                         /* Already attached */
   1.350 -                        consoleAttached = 1;
   1.351 -                    } else {
   1.352 -                        OutputDebugString(TEXT("Error attaching console\r\n"));
   1.353 -                        consoleAttached = -1;
   1.354 -                    }
   1.355 -                } else {
   1.356 -                    /* Newly attached */
   1.357 -                    consoleAttached = 1;
   1.358 -                }
   1.359 -			
   1.360 -                if (consoleAttached == 1) {
   1.361 -                        stderrHandle = GetStdHandle(STD_ERROR_HANDLE);
   1.362 -                }
   1.363 -        }
   1.364 -#endif /* ifndef __WINRT__ */
   1.365 -
   1.366 -        length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1 + 1 + 1;
   1.367 -        output = SDL_stack_alloc(char, length);
   1.368 -        SDL_snprintf(output, length, "%s: %s\r\n", SDL_priority_prefixes[priority], message);
   1.369 -        tstr = WIN_UTF8ToString(output);
   1.370 -        
   1.371 -        /* Output to debugger */
   1.372 -        OutputDebugString(tstr);
   1.373 -       
   1.374 -#ifndef __WINRT__
   1.375 -        /* Screen output to stderr, if console was attached. */
   1.376 -        if (consoleAttached == 1) {
   1.377 -                if (!WriteConsole(stderrHandle, tstr, lstrlen(tstr), &charsWritten, NULL)) {
   1.378 -                    OutputDebugString(TEXT("Error calling WriteConsole\r\n"));
   1.379 -                }
   1.380 -                if (charsWritten == ERROR_NOT_ENOUGH_MEMORY) {
   1.381 -                    OutputDebugString(TEXT("Insufficient heap memory to write message\r\n"));
   1.382 -                }
   1.383 -        }
   1.384 -#endif /* ifndef __WINRT__ */
   1.385 -
   1.386 -        SDL_free(tstr);
   1.387 -        SDL_stack_free(output);
   1.388 -    }
   1.389 -#elif defined(__ANDROID__)
   1.390 -    {
   1.391 -        char tag[32];
   1.392 -
   1.393 -        SDL_snprintf(tag, SDL_arraysize(tag), "SDL/%s", GetCategoryPrefix(category));
   1.394 -        __android_log_write(SDL_android_priority[priority], tag, message);
   1.395 -    }
   1.396 -#elif defined(__APPLE__) && defined(SDL_VIDEO_DRIVER_COCOA)
   1.397 -    /* Technically we don't need SDL_VIDEO_DRIVER_COCOA, but that's where this function is defined for now.
   1.398 -    */
   1.399 -    extern void SDL_NSLog(const char *text);
   1.400 -    {
   1.401 -        char *text;
   1.402 -
   1.403 -        text = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE);
   1.404 -        if (text) {
   1.405 -            SDL_snprintf(text, SDL_MAX_LOG_MESSAGE, "%s: %s", SDL_priority_prefixes[priority], message);
   1.406 -            SDL_NSLog(text);
   1.407 -            SDL_stack_free(text);
   1.408 -            return;
   1.409 -        }
   1.410 -    }
   1.411 -#elif defined(__PSP__)
   1.412 -    {
   1.413 -        FILE*        pFile;
   1.414 -        pFile = fopen ("SDL_Log.txt", "a");
   1.415 -        fprintf(pFile, "%s: %s\n", SDL_priority_prefixes[priority], message);
   1.416 -        fclose (pFile);
   1.417 -    }
   1.418 -#endif
   1.419 -#if HAVE_STDIO_H
   1.420 -    fprintf(stderr, "%s: %s\n", SDL_priority_prefixes[priority], message);
   1.421 -#endif
   1.422 -}
   1.423 -
   1.424 -void
   1.425 -SDL_LogGetOutputFunction(SDL_LogOutputFunction *callback, void **userdata)
   1.426 -{
   1.427 -    if (callback) {
   1.428 -        *callback = SDL_log_function;
   1.429 -    }
   1.430 -    if (userdata) {
   1.431 -        *userdata = SDL_log_userdata;
   1.432 -    }
   1.433 -}
   1.434 -
   1.435 -void
   1.436 -SDL_LogSetOutputFunction(SDL_LogOutputFunction callback, void *userdata)
   1.437 -{
   1.438 -    SDL_log_function = callback;
   1.439 -    SDL_log_userdata = userdata;
   1.440 -}
   1.441 -
   1.442 -/* vi: set ts=4 sw=4 expandtab: */
   1.443 +/*
   1.444 +  Simple DirectMedia Layer
   1.445 +  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
   1.446 +
   1.447 +  This software is provided 'as-is', without any express or implied
   1.448 +  warranty.  In no event will the authors be held liable for any damages
   1.449 +  arising from the use of this software.
   1.450 +
   1.451 +  Permission is granted to anyone to use this software for any purpose,
   1.452 +  including commercial applications, and to alter it and redistribute it
   1.453 +  freely, subject to the following restrictions:
   1.454 +
   1.455 +  1. The origin of this software must not be misrepresented; you must not
   1.456 +     claim that you wrote the original software. If you use this software
   1.457 +     in a product, an acknowledgment in the product documentation would be
   1.458 +     appreciated but is not required.
   1.459 +  2. Altered source versions must be plainly marked as such, and must not be
   1.460 +     misrepresented as being the original software.
   1.461 +  3. This notice may not be removed or altered from any source distribution.
   1.462 +*/
   1.463 +#include "SDL_config.h"
   1.464 +
   1.465 +#if defined(__WIN32__) || defined(__WINRT__)
   1.466 +#include "core/windows/SDL_windows.h"
   1.467 +#endif
   1.468 +
   1.469 +/* Simple log messages in SDL */
   1.470 +
   1.471 +#include "SDL_log.h"
   1.472 +
   1.473 +#if HAVE_STDIO_H
   1.474 +#include <stdio.h>
   1.475 +#endif
   1.476 +
   1.477 +#if defined(__ANDROID__)
   1.478 +#include <android/log.h>
   1.479 +#endif
   1.480 +
   1.481 +#define DEFAULT_PRIORITY                SDL_LOG_PRIORITY_CRITICAL
   1.482 +#define DEFAULT_ASSERT_PRIORITY         SDL_LOG_PRIORITY_WARN
   1.483 +#define DEFAULT_APPLICATION_PRIORITY    SDL_LOG_PRIORITY_INFO
   1.484 +#define DEFAULT_TEST_PRIORITY           SDL_LOG_PRIORITY_VERBOSE
   1.485 +
   1.486 +/* Forward definition of error function */
   1.487 +extern int SDL_SetError(const char *fmt, ...);
   1.488 +
   1.489 +typedef struct SDL_LogLevel
   1.490 +{
   1.491 +    int category;
   1.492 +    SDL_LogPriority priority;
   1.493 +    struct SDL_LogLevel *next;
   1.494 +} SDL_LogLevel;
   1.495 +
   1.496 +/* The default log output function */
   1.497 +static void SDL_LogOutput(void *userdata,
   1.498 +                          int category, SDL_LogPriority priority,
   1.499 +                          const char *message);
   1.500 +
   1.501 +static SDL_LogLevel *SDL_loglevels;
   1.502 +static SDL_LogPriority SDL_default_priority = DEFAULT_PRIORITY;
   1.503 +static SDL_LogPriority SDL_assert_priority = DEFAULT_ASSERT_PRIORITY;
   1.504 +static SDL_LogPriority SDL_application_priority = DEFAULT_APPLICATION_PRIORITY;
   1.505 +static SDL_LogPriority SDL_test_priority = DEFAULT_TEST_PRIORITY;
   1.506 +static SDL_LogOutputFunction SDL_log_function = SDL_LogOutput;
   1.507 +static void *SDL_log_userdata = NULL;
   1.508 +
   1.509 +static const char *SDL_priority_prefixes[SDL_NUM_LOG_PRIORITIES] = {
   1.510 +    NULL,
   1.511 +    "VERBOSE",
   1.512 +    "DEBUG",
   1.513 +    "INFO",
   1.514 +    "WARN",
   1.515 +    "ERROR",
   1.516 +    "CRITICAL"
   1.517 +};
   1.518 +
   1.519 +#ifdef __ANDROID__
   1.520 +static const char *SDL_category_prefixes[SDL_LOG_CATEGORY_RESERVED1] = {
   1.521 +    "APP",
   1.522 +    "ERROR",
   1.523 +    "SYSTEM",
   1.524 +    "AUDIO",
   1.525 +    "VIDEO",
   1.526 +    "RENDER",
   1.527 +    "INPUT"
   1.528 +};
   1.529 +
   1.530 +static int SDL_android_priority[SDL_NUM_LOG_PRIORITIES] = {
   1.531 +    ANDROID_LOG_UNKNOWN,
   1.532 +    ANDROID_LOG_VERBOSE,
   1.533 +    ANDROID_LOG_DEBUG,
   1.534 +    ANDROID_LOG_INFO,
   1.535 +    ANDROID_LOG_WARN,
   1.536 +    ANDROID_LOG_ERROR,
   1.537 +    ANDROID_LOG_FATAL
   1.538 +};
   1.539 +#endif /* __ANDROID__ */
   1.540 +
   1.541 +
   1.542 +void
   1.543 +SDL_LogSetAllPriority(SDL_LogPriority priority)
   1.544 +{
   1.545 +    SDL_LogLevel *entry;
   1.546 +
   1.547 +    for (entry = SDL_loglevels; entry; entry = entry->next) {
   1.548 +        entry->priority = priority;
   1.549 +    }
   1.550 +    SDL_default_priority = priority;
   1.551 +    SDL_assert_priority = priority;
   1.552 +    SDL_application_priority = priority;
   1.553 +}
   1.554 +
   1.555 +void
   1.556 +SDL_LogSetPriority(int category, SDL_LogPriority priority)
   1.557 +{
   1.558 +    SDL_LogLevel *entry;
   1.559 +
   1.560 +    for (entry = SDL_loglevels; entry; entry = entry->next) {
   1.561 +        if (entry->category == category) {
   1.562 +            entry->priority = priority;
   1.563 +            return;
   1.564 +        }
   1.565 +    }
   1.566 +
   1.567 +    /* Create a new entry */
   1.568 +    entry = (SDL_LogLevel *)SDL_malloc(sizeof(*entry));
   1.569 +    if (entry) {
   1.570 +        entry->category = category;
   1.571 +        entry->priority = priority;
   1.572 +        entry->next = SDL_loglevels;
   1.573 +        SDL_loglevels = entry;
   1.574 +    }
   1.575 +}
   1.576 +
   1.577 +SDL_LogPriority
   1.578 +SDL_LogGetPriority(int category)
   1.579 +{
   1.580 +    SDL_LogLevel *entry;
   1.581 +
   1.582 +    for (entry = SDL_loglevels; entry; entry = entry->next) {
   1.583 +        if (entry->category == category) {
   1.584 +            return entry->priority;
   1.585 +        }
   1.586 +    }
   1.587 +
   1.588 +    if (category == SDL_LOG_CATEGORY_TEST) {
   1.589 +        return SDL_test_priority;
   1.590 +    } else if (category == SDL_LOG_CATEGORY_APPLICATION) {
   1.591 +        return SDL_application_priority;
   1.592 +    } else if (category == SDL_LOG_CATEGORY_ASSERT) {
   1.593 +        return SDL_assert_priority;
   1.594 +    } else {
   1.595 +        return SDL_default_priority;
   1.596 +    }
   1.597 +}
   1.598 +
   1.599 +void
   1.600 +SDL_LogResetPriorities(void)
   1.601 +{
   1.602 +    SDL_LogLevel *entry;
   1.603 +
   1.604 +    while (SDL_loglevels) {
   1.605 +        entry = SDL_loglevels;
   1.606 +        SDL_loglevels = entry->next;
   1.607 +        SDL_free(entry);
   1.608 +    }
   1.609 +
   1.610 +    SDL_default_priority = DEFAULT_PRIORITY;
   1.611 +    SDL_assert_priority = DEFAULT_ASSERT_PRIORITY;
   1.612 +    SDL_application_priority = DEFAULT_APPLICATION_PRIORITY;
   1.613 +    SDL_test_priority = DEFAULT_TEST_PRIORITY;
   1.614 +}
   1.615 +
   1.616 +void
   1.617 +SDL_Log(const char *fmt, ...)
   1.618 +{
   1.619 +    va_list ap;
   1.620 +
   1.621 +    va_start(ap, fmt);
   1.622 +    SDL_LogMessageV(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, fmt, ap);
   1.623 +    va_end(ap);
   1.624 +}
   1.625 +
   1.626 +void
   1.627 +SDL_LogVerbose(int category, const char *fmt, ...)
   1.628 +{
   1.629 +    va_list ap;
   1.630 +
   1.631 +    va_start(ap, fmt);
   1.632 +    SDL_LogMessageV(category, SDL_LOG_PRIORITY_VERBOSE, fmt, ap);
   1.633 +    va_end(ap);
   1.634 +}
   1.635 +
   1.636 +void
   1.637 +SDL_LogDebug(int category, const char *fmt, ...)
   1.638 +{
   1.639 +    va_list ap;
   1.640 +
   1.641 +    va_start(ap, fmt);
   1.642 +    SDL_LogMessageV(category, SDL_LOG_PRIORITY_DEBUG, fmt, ap);
   1.643 +    va_end(ap);
   1.644 +}
   1.645 +
   1.646 +void
   1.647 +SDL_LogInfo(int category, const char *fmt, ...)
   1.648 +{
   1.649 +    va_list ap;
   1.650 +
   1.651 +    va_start(ap, fmt);
   1.652 +    SDL_LogMessageV(category, SDL_LOG_PRIORITY_INFO, fmt, ap);
   1.653 +    va_end(ap);
   1.654 +}
   1.655 +
   1.656 +void
   1.657 +SDL_LogWarn(int category, const char *fmt, ...)
   1.658 +{
   1.659 +    va_list ap;
   1.660 +
   1.661 +    va_start(ap, fmt);
   1.662 +    SDL_LogMessageV(category, SDL_LOG_PRIORITY_WARN, fmt, ap);
   1.663 +    va_end(ap);
   1.664 +}
   1.665 +
   1.666 +void
   1.667 +SDL_LogError(int category, const char *fmt, ...)
   1.668 +{
   1.669 +    va_list ap;
   1.670 +
   1.671 +    va_start(ap, fmt);
   1.672 +    SDL_LogMessageV(category, SDL_LOG_PRIORITY_ERROR, fmt, ap);
   1.673 +    va_end(ap);
   1.674 +}
   1.675 +
   1.676 +void
   1.677 +SDL_LogCritical(int category, const char *fmt, ...)
   1.678 +{
   1.679 +    va_list ap;
   1.680 +
   1.681 +    va_start(ap, fmt);
   1.682 +    SDL_LogMessageV(category, SDL_LOG_PRIORITY_CRITICAL, fmt, ap);
   1.683 +    va_end(ap);
   1.684 +}
   1.685 +
   1.686 +void
   1.687 +SDL_LogMessage(int category, SDL_LogPriority priority, const char *fmt, ...)
   1.688 +{
   1.689 +    va_list ap;
   1.690 +
   1.691 +    va_start(ap, fmt);
   1.692 +    SDL_LogMessageV(category, priority, fmt, ap);
   1.693 +    va_end(ap);
   1.694 +}
   1.695 +
   1.696 +#ifdef __ANDROID__
   1.697 +static const char *
   1.698 +GetCategoryPrefix(int category)
   1.699 +{
   1.700 +    if (category < SDL_LOG_CATEGORY_RESERVED1) {
   1.701 +        return SDL_category_prefixes[category];
   1.702 +    }
   1.703 +    if (category < SDL_LOG_CATEGORY_CUSTOM) {
   1.704 +        return "RESERVED";
   1.705 +    }
   1.706 +    return "CUSTOM";
   1.707 +}
   1.708 +#endif /* __ANDROID__ */
   1.709 +
   1.710 +void
   1.711 +SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list ap)
   1.712 +{
   1.713 +    char *message;
   1.714 +    size_t len;
   1.715 +
   1.716 +    /* Nothing to do if we don't have an output function */
   1.717 +    if (!SDL_log_function) {
   1.718 +        return;
   1.719 +    }
   1.720 +
   1.721 +    /* Make sure we don't exceed array bounds */
   1.722 +    if ((int)priority < 0 || priority >= SDL_NUM_LOG_PRIORITIES) {
   1.723 +        return;
   1.724 +    }
   1.725 +
   1.726 +    /* See if we want to do anything with this message */
   1.727 +    if (priority < SDL_LogGetPriority(category)) {
   1.728 +        return;
   1.729 +    }
   1.730 +
   1.731 +    message = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE);
   1.732 +    if (!message) {
   1.733 +        return;
   1.734 +    }
   1.735 +
   1.736 +    SDL_vsnprintf(message, SDL_MAX_LOG_MESSAGE, fmt, ap);
   1.737 +
   1.738 +    /* Chop off final endline. */
   1.739 +    len = SDL_strlen(message);
   1.740 +    if ((len > 0) && (message[len-1] == '\n')) {
   1.741 +        message[--len] = '\0';
   1.742 +        if ((len > 0) && (message[len-1] == '\r')) {  /* catch "\r\n", too. */
   1.743 +            message[--len] = '\0';
   1.744 +        }
   1.745 +    }
   1.746 +
   1.747 +    SDL_log_function(SDL_log_userdata, category, priority, message);
   1.748 +    SDL_stack_free(message);
   1.749 +}
   1.750 +
   1.751 +#if defined(__WIN32__)
   1.752 +/* Flag tracking the attachment of the console: 0=unattached, 1=attached, -1=error */
   1.753 +static int consoleAttached = 0;
   1.754 +
   1.755 +/* Handle to stderr output of console. */
   1.756 +static HANDLE stderrHandle = NULL;
   1.757 +#endif
   1.758 +
   1.759 +static void
   1.760 +SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
   1.761 +              const char *message)
   1.762 +{
   1.763 +#if defined(__WIN32__) || defined(__WINRT__)
   1.764 +    /* Way too many allocations here, urgh */
   1.765 +    /* Note: One can't call SDL_SetError here, since that function itself logs. */
   1.766 +    {
   1.767 +        char *output;
   1.768 +        size_t length;
   1.769 +        LPTSTR tstr;
   1.770 +
   1.771 +#ifndef __WINRT__
   1.772 +        BOOL attachResult;
   1.773 +        DWORD attachError;
   1.774 +        unsigned long charsWritten; 
   1.775 +
   1.776 +        /* Maybe attach console and get stderr handle */
   1.777 +        if (consoleAttached == 0) {
   1.778 +            attachResult = AttachConsole(ATTACH_PARENT_PROCESS);
   1.779 +            if (!attachResult) {
   1.780 +                    attachError = GetLastError();
   1.781 +                    if (attachError == ERROR_INVALID_HANDLE) {
   1.782 +                        OutputDebugString(TEXT("Parent process has no console\r\n"));
   1.783 +                        consoleAttached = -1;
   1.784 +                    } else if (attachError == ERROR_GEN_FAILURE) {
   1.785 +                         OutputDebugString(TEXT("Could not attach to console of parent process\r\n"));
   1.786 +                         consoleAttached = -1;
   1.787 +                    } else if (attachError == ERROR_ACCESS_DENIED) {  
   1.788 +                         /* Already attached */
   1.789 +                        consoleAttached = 1;
   1.790 +                    } else {
   1.791 +                        OutputDebugString(TEXT("Error attaching console\r\n"));
   1.792 +                        consoleAttached = -1;
   1.793 +                    }
   1.794 +                } else {
   1.795 +                    /* Newly attached */
   1.796 +                    consoleAttached = 1;
   1.797 +                }
   1.798 +			
   1.799 +                if (consoleAttached == 1) {
   1.800 +                        stderrHandle = GetStdHandle(STD_ERROR_HANDLE);
   1.801 +                }
   1.802 +        }
   1.803 +#endif /* ifndef __WINRT__ */
   1.804 +
   1.805 +        length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1 + 1 + 1;
   1.806 +        output = SDL_stack_alloc(char, length);
   1.807 +        SDL_snprintf(output, length, "%s: %s\r\n", SDL_priority_prefixes[priority], message);
   1.808 +        tstr = WIN_UTF8ToString(output);
   1.809 +        
   1.810 +        /* Output to debugger */
   1.811 +        OutputDebugString(tstr);
   1.812 +       
   1.813 +#ifndef __WINRT__
   1.814 +        /* Screen output to stderr, if console was attached. */
   1.815 +        if (consoleAttached == 1) {
   1.816 +                if (!WriteConsole(stderrHandle, tstr, lstrlen(tstr), &charsWritten, NULL)) {
   1.817 +                    OutputDebugString(TEXT("Error calling WriteConsole\r\n"));
   1.818 +                }
   1.819 +                if (charsWritten == ERROR_NOT_ENOUGH_MEMORY) {
   1.820 +                    OutputDebugString(TEXT("Insufficient heap memory to write message\r\n"));
   1.821 +                }
   1.822 +        }
   1.823 +#endif /* ifndef __WINRT__ */
   1.824 +
   1.825 +        SDL_free(tstr);
   1.826 +        SDL_stack_free(output);
   1.827 +    }
   1.828 +#elif defined(__ANDROID__)
   1.829 +    {
   1.830 +        char tag[32];
   1.831 +
   1.832 +        SDL_snprintf(tag, SDL_arraysize(tag), "SDL/%s", GetCategoryPrefix(category));
   1.833 +        __android_log_write(SDL_android_priority[priority], tag, message);
   1.834 +    }
   1.835 +#elif defined(__APPLE__) && defined(SDL_VIDEO_DRIVER_COCOA)
   1.836 +    /* Technically we don't need SDL_VIDEO_DRIVER_COCOA, but that's where this function is defined for now.
   1.837 +    */
   1.838 +    extern void SDL_NSLog(const char *text);
   1.839 +    {
   1.840 +        char *text;
   1.841 +
   1.842 +        text = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE);
   1.843 +        if (text) {
   1.844 +            SDL_snprintf(text, SDL_MAX_LOG_MESSAGE, "%s: %s", SDL_priority_prefixes[priority], message);
   1.845 +            SDL_NSLog(text);
   1.846 +            SDL_stack_free(text);
   1.847 +            return;
   1.848 +        }
   1.849 +    }
   1.850 +#elif defined(__PSP__)
   1.851 +    {
   1.852 +        FILE*        pFile;
   1.853 +        pFile = fopen ("SDL_Log.txt", "a");
   1.854 +        fprintf(pFile, "%s: %s\n", SDL_priority_prefixes[priority], message);
   1.855 +        fclose (pFile);
   1.856 +    }
   1.857 +#endif
   1.858 +#if HAVE_STDIO_H
   1.859 +    fprintf(stderr, "%s: %s\n", SDL_priority_prefixes[priority], message);
   1.860 +#endif
   1.861 +}
   1.862 +
   1.863 +void
   1.864 +SDL_LogGetOutputFunction(SDL_LogOutputFunction *callback, void **userdata)
   1.865 +{
   1.866 +    if (callback) {
   1.867 +        *callback = SDL_log_function;
   1.868 +    }
   1.869 +    if (userdata) {
   1.870 +        *userdata = SDL_log_userdata;
   1.871 +    }
   1.872 +}
   1.873 +
   1.874 +void
   1.875 +SDL_LogSetOutputFunction(SDL_LogOutputFunction callback, void *userdata)
   1.876 +{
   1.877 +    SDL_log_function = callback;
   1.878 +    SDL_log_userdata = userdata;
   1.879 +}
   1.880 +
   1.881 +/* vi: set ts=4 sw=4 expandtab: */