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