src/SDL_log.c
author Ryan C. Gordon <icculus@icculus.org>
Mon, 09 Apr 2012 23:55:43 -0400
changeset 6305 601b0e251822
parent 6138 4c64952a58fb
child 6616 4f272256d172
child 8325 33cbbdd796ec
permissions -rwxr-xr-x
SDL_ExitProcess() was ignoring exit code parameter.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2012 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_config.h"
    22 
    23 /* Simple log messages in SDL */
    24 
    25 #include "SDL_log.h"
    26 
    27 #if HAVE_STDIO_H
    28 #include <stdio.h>
    29 #endif
    30 
    31 #if defined(__WIN32__)
    32 #include "core/windows/SDL_windows.h"
    33 #elif defined(__ANDROID__)
    34 #include <android/log.h>
    35 #endif
    36 
    37 #define DEFAULT_PRIORITY                SDL_LOG_PRIORITY_CRITICAL
    38 #define DEFAULT_APPLICATION_PRIORITY    SDL_LOG_PRIORITY_INFO
    39 
    40 typedef struct SDL_LogLevel
    41 {
    42     int category;
    43     SDL_LogPriority priority;
    44     struct SDL_LogLevel *next;
    45 } SDL_LogLevel;
    46 
    47 /* The default log output function */
    48 static void SDL_LogOutput(void *userdata,
    49                           int category, SDL_LogPriority priority,
    50                           const char *message);
    51 
    52 static SDL_LogLevel *SDL_loglevels;
    53 static SDL_LogPriority SDL_application_priority = DEFAULT_APPLICATION_PRIORITY;
    54 static SDL_LogPriority SDL_default_priority = DEFAULT_PRIORITY;
    55 static SDL_LogOutputFunction SDL_log_function = SDL_LogOutput;
    56 static void *SDL_log_userdata = NULL;
    57 
    58 static const char *SDL_priority_prefixes[SDL_NUM_LOG_PRIORITIES] = {
    59     NULL,
    60     "VERBOSE",
    61     "DEBUG",
    62     "INFO",
    63     "WARN",
    64     "ERROR",
    65     "CRITICAL"
    66 };
    67 
    68 #ifdef __ANDROID__
    69 static const char *SDL_category_prefixes[SDL_LOG_CATEGORY_RESERVED1] = {
    70     "APP",
    71     "ERROR",
    72     "SYSTEM",
    73     "AUDIO",
    74     "VIDEO",
    75     "RENDER",
    76     "INPUT"
    77 };
    78 
    79 static int SDL_android_priority[SDL_NUM_LOG_PRIORITIES] = {
    80     ANDROID_LOG_VERBOSE,
    81     ANDROID_LOG_DEBUG,
    82     ANDROID_LOG_INFO,
    83     ANDROID_LOG_WARN,
    84     ANDROID_LOG_ERROR,
    85     ANDROID_LOG_FATAL
    86 };
    87 #endif /* __ANDROID__ */
    88 
    89 
    90 void
    91 SDL_LogSetAllPriority(SDL_LogPriority priority)
    92 {
    93     SDL_LogLevel *entry;
    94 
    95     for (entry = SDL_loglevels; entry; entry = entry->next) {
    96         entry->priority = priority;
    97     }
    98     SDL_application_priority = SDL_default_priority = priority;
    99 }
   100 
   101 void
   102 SDL_LogSetPriority(int category, SDL_LogPriority priority)
   103 {
   104     SDL_LogLevel *entry;
   105 
   106     for (entry = SDL_loglevels; entry; entry = entry->next) {
   107         if (entry->category == category) {
   108             entry->priority = priority;
   109             return;
   110         }
   111     }
   112 
   113     /* Create a new entry */
   114     entry = (SDL_LogLevel *)SDL_malloc(sizeof(*entry));
   115     if (entry) {
   116         entry->category = category;
   117         entry->priority = priority;
   118         entry->next = SDL_loglevels;
   119         SDL_loglevels = entry;
   120     }
   121 }
   122 
   123 SDL_LogPriority
   124 SDL_LogGetPriority(int category)
   125 {
   126     SDL_LogLevel *entry;
   127 
   128     for (entry = SDL_loglevels; entry; entry = entry->next) {
   129         if (entry->category == category) {
   130             return entry->priority;
   131         }
   132     }
   133 
   134     if (category == SDL_LOG_CATEGORY_APPLICATION) {
   135         return SDL_application_priority;
   136     } else {
   137         return SDL_default_priority;
   138     }
   139 }
   140 
   141 void
   142 SDL_LogResetPriorities(void)
   143 {
   144     SDL_LogLevel *entry;
   145 
   146     while (SDL_loglevels) {
   147         entry = SDL_loglevels;
   148         SDL_loglevels = entry->next;
   149         SDL_free(entry);
   150     }
   151 
   152     SDL_application_priority = DEFAULT_APPLICATION_PRIORITY;
   153     SDL_default_priority = DEFAULT_PRIORITY;
   154 }
   155 
   156 void
   157 SDL_Log(const char *fmt, ...)
   158 {
   159     va_list ap;
   160 
   161     va_start(ap, fmt);
   162     SDL_LogMessageV(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, fmt, ap);
   163     va_end(ap);
   164 }
   165 
   166 void
   167 SDL_LogVerbose(int category, const char *fmt, ...)
   168 {
   169     va_list ap;
   170 
   171     va_start(ap, fmt);
   172     SDL_LogMessageV(category, SDL_LOG_PRIORITY_VERBOSE, fmt, ap);
   173     va_end(ap);
   174 }
   175 
   176 void
   177 SDL_LogDebug(int category, const char *fmt, ...)
   178 {
   179     va_list ap;
   180 
   181     va_start(ap, fmt);
   182     SDL_LogMessageV(category, SDL_LOG_PRIORITY_DEBUG, fmt, ap);
   183     va_end(ap);
   184 }
   185 
   186 void
   187 SDL_LogInfo(int category, const char *fmt, ...)
   188 {
   189     va_list ap;
   190 
   191     va_start(ap, fmt);
   192     SDL_LogMessageV(category, SDL_LOG_PRIORITY_INFO, fmt, ap);
   193     va_end(ap);
   194 }
   195 
   196 void
   197 SDL_LogWarn(int category, const char *fmt, ...)
   198 {
   199     va_list ap;
   200 
   201     va_start(ap, fmt);
   202     SDL_LogMessageV(category, SDL_LOG_PRIORITY_WARN, fmt, ap);
   203     va_end(ap);
   204 }
   205 
   206 void
   207 SDL_LogError(int category, const char *fmt, ...)
   208 {
   209     va_list ap;
   210 
   211     va_start(ap, fmt);
   212     SDL_LogMessageV(category, SDL_LOG_PRIORITY_ERROR, fmt, ap);
   213     va_end(ap);
   214 }
   215 
   216 void
   217 SDL_LogCritical(int category, const char *fmt, ...)
   218 {
   219     va_list ap;
   220 
   221     va_start(ap, fmt);
   222     SDL_LogMessageV(category, SDL_LOG_PRIORITY_CRITICAL, fmt, ap);
   223     va_end(ap);
   224 }
   225 
   226 void
   227 SDL_LogMessage(int category, SDL_LogPriority priority, const char *fmt, ...)
   228 {
   229     va_list ap;
   230 
   231     va_start(ap, fmt);
   232     SDL_LogMessageV(category, priority, fmt, ap);
   233     va_end(ap);
   234 }
   235 
   236 #ifdef __ANDROID__
   237 static const char *
   238 GetCategoryPrefix(int category)
   239 {
   240     if (category < SDL_LOG_CATEGORY_RESERVED1) {
   241         return SDL_category_prefixes[category];
   242     }
   243     if (category < SDL_LOG_CATEGORY_CUSTOM) {
   244         return "RESERVED";
   245     }
   246     return "CUSTOM";
   247 }
   248 #endif /* __ANDROID__ */
   249 
   250 void
   251 SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list ap)
   252 {
   253     char *message;
   254 
   255     /* Nothing to do if we don't have an output function */
   256     if (!SDL_log_function) {
   257         return;
   258     }
   259 
   260     /* Make sure we don't exceed array bounds */
   261     if ((int)priority < 0 || priority >= SDL_NUM_LOG_PRIORITIES) {
   262         return;
   263     }
   264 
   265     /* See if we want to do anything with this message */
   266     if (priority < SDL_LogGetPriority(category)) {
   267         return;
   268     }
   269 
   270     message = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE);
   271     if (!message) {
   272         return;
   273     }
   274     SDL_vsnprintf(message, SDL_MAX_LOG_MESSAGE, fmt, ap);
   275     SDL_log_function(SDL_log_userdata, category, priority, message);
   276     SDL_stack_free(message);
   277 }
   278 
   279 static void
   280 SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
   281               const char *message)
   282 {
   283 #if defined(__WIN32__)
   284     /* Way too many allocations here, urgh */
   285     {
   286         char *output;
   287         size_t length;
   288         LPTSTR tstr;
   289 
   290         length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1;
   291         output = SDL_stack_alloc(char, length);
   292         SDL_snprintf(output, length, "%s: %s", SDL_priority_prefixes[priority], message);
   293         tstr = WIN_UTF8ToString(output);
   294         OutputDebugString(tstr);
   295         SDL_free(tstr);
   296         SDL_stack_free(output);
   297     }
   298 #elif defined(__ANDROID__)
   299     {
   300         char tag[32];
   301 
   302         SDL_snprintf(tag, SDL_arraysize(tag), "SDL/%s", GetCategoryPrefix(category));
   303         __android_log_write(SDL_android_priority[priority], tag, message);
   304     }
   305 #endif
   306 #if HAVE_STDIO_H
   307     fprintf(stderr, "%s: %s\n", SDL_priority_prefixes[priority], message);
   308 #endif
   309 }
   310 
   311 void
   312 SDL_LogGetOutputFunction(SDL_LogOutputFunction *callback, void **userdata)
   313 {
   314     if (callback) {
   315         *callback = SDL_log_function;
   316     }
   317     if (userdata) {
   318         *userdata = SDL_log_userdata;
   319     }
   320 }
   321 
   322 void
   323 SDL_LogSetOutputFunction(SDL_LogOutputFunction callback, void *userdata)
   324 {
   325     SDL_log_function = callback;
   326     SDL_log_userdata = userdata;
   327 }
   328 
   329 /* vi: set ts=4 sw=4 expandtab: */