cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_log.c (12087B)


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