src/SDL_log.c
author Ryan C. Gordon <icculus@icculus.org>
Thu, 21 Apr 2016 03:16:44 -0400
changeset 11729 d1ce8396c356
parent 11722 27dd67e1c5eb
child 11811 5d94cb6b24d3
permissions -rw-r--r--
Initial shot at a renderer target for Apple's Metal API.

This isn't complete, but is enough to run testsprite2. It's currently
Mac-only; with a little work to figure out how to properly glue in a Metal
layer to a UIView, this will likely work on iOS, too.

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