src/SDL_log.c
author Gabriel Jacobo <gabomdq@gmail.com>
Mon, 01 Apr 2013 13:20:22 -0300
changeset 7039 f69b305b053d
parent 7009 161b7b6a5303
child 7191 75360622e65f
child 8460 f483e8bdae3c
permissions -rw-r--r--
Backed out changeset: 9cef1005df5f
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2013 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_ASSERT_PRIORITY         SDL_LOG_PRIORITY_WARN
    39 #define DEFAULT_APPLICATION_PRIORITY    SDL_LOG_PRIORITY_INFO
    40 #define DEFAULT_TEST_PRIORITY           SDL_LOG_PRIORITY_VERBOSE
    41 
    42 typedef struct SDL_LogLevel
    43 {
    44     int category;
    45     SDL_LogPriority priority;
    46     struct SDL_LogLevel *next;
    47 } SDL_LogLevel;
    48 
    49 /* The default log output function */
    50 static void SDL_LogOutput(void *userdata,
    51                           int category, SDL_LogPriority priority,
    52                           const char *message);
    53 
    54 static SDL_LogLevel *SDL_loglevels;
    55 static SDL_LogPriority SDL_default_priority = DEFAULT_PRIORITY;
    56 static SDL_LogPriority SDL_assert_priority = DEFAULT_ASSERT_PRIORITY;
    57 static SDL_LogPriority SDL_application_priority = DEFAULT_APPLICATION_PRIORITY;
    58 static SDL_LogPriority SDL_test_priority = DEFAULT_TEST_PRIORITY;
    59 static SDL_LogOutputFunction SDL_log_function = SDL_LogOutput;
    60 static void *SDL_log_userdata = NULL;
    61 
    62 static const char *SDL_priority_prefixes[SDL_NUM_LOG_PRIORITIES] = {
    63     NULL,
    64     "VERBOSE",
    65     "DEBUG",
    66     "INFO",
    67     "WARN",
    68     "ERROR",
    69     "CRITICAL"
    70 };
    71 
    72 #ifdef __ANDROID__
    73 static const char *SDL_category_prefixes[SDL_LOG_CATEGORY_RESERVED1] = {
    74     "APP",
    75     "ERROR",
    76     "SYSTEM",
    77     "AUDIO",
    78     "VIDEO",
    79     "RENDER",
    80     "INPUT"
    81 };
    82 
    83 static int SDL_android_priority[SDL_NUM_LOG_PRIORITIES] = {
    84     ANDROID_LOG_VERBOSE,
    85     ANDROID_LOG_DEBUG,
    86     ANDROID_LOG_INFO,
    87     ANDROID_LOG_WARN,
    88     ANDROID_LOG_ERROR,
    89     ANDROID_LOG_FATAL
    90 };
    91 #endif /* __ANDROID__ */
    92 
    93 
    94 void
    95 SDL_LogSetAllPriority(SDL_LogPriority priority)
    96 {
    97     SDL_LogLevel *entry;
    98 
    99     for (entry = SDL_loglevels; entry; entry = entry->next) {
   100         entry->priority = priority;
   101     }
   102     SDL_default_priority = priority;
   103     SDL_assert_priority = priority;
   104     SDL_application_priority = priority;
   105 }
   106 
   107 void
   108 SDL_LogSetPriority(int category, SDL_LogPriority priority)
   109 {
   110     SDL_LogLevel *entry;
   111 
   112     for (entry = SDL_loglevels; entry; entry = entry->next) {
   113         if (entry->category == category) {
   114             entry->priority = priority;
   115             return;
   116         }
   117     }
   118 
   119     /* Create a new entry */
   120     entry = (SDL_LogLevel *)SDL_malloc(sizeof(*entry));
   121     if (entry) {
   122         entry->category = category;
   123         entry->priority = priority;
   124         entry->next = SDL_loglevels;
   125         SDL_loglevels = entry;
   126     }
   127 }
   128 
   129 SDL_LogPriority
   130 SDL_LogGetPriority(int category)
   131 {
   132     SDL_LogLevel *entry;
   133 
   134     for (entry = SDL_loglevels; entry; entry = entry->next) {
   135         if (entry->category == category) {
   136             return entry->priority;
   137         }
   138     }
   139 
   140     if (category == SDL_LOG_CATEGORY_TEST) {
   141         return SDL_test_priority;    
   142     } else if (category == SDL_LOG_CATEGORY_APPLICATION) {
   143         return SDL_application_priority;
   144     } else if (category == SDL_LOG_CATEGORY_ASSERT) {
   145         return SDL_assert_priority;
   146     } else {
   147         return SDL_default_priority;
   148     }
   149 }
   150 
   151 void
   152 SDL_LogResetPriorities(void)
   153 {
   154     SDL_LogLevel *entry;
   155 
   156     while (SDL_loglevels) {
   157         entry = SDL_loglevels;
   158         SDL_loglevels = entry->next;
   159         SDL_free(entry);
   160     }
   161 
   162     SDL_default_priority = DEFAULT_PRIORITY;
   163     SDL_assert_priority = DEFAULT_ASSERT_PRIORITY;
   164     SDL_application_priority = DEFAULT_APPLICATION_PRIORITY;
   165     SDL_test_priority = DEFAULT_TEST_PRIORITY;
   166 }
   167 
   168 void
   169 SDL_Log(const char *fmt, ...)
   170 {
   171     va_list ap;
   172 
   173     va_start(ap, fmt);
   174     SDL_LogMessageV(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, fmt, ap);
   175     va_end(ap);
   176 }
   177 
   178 void
   179 SDL_LogVerbose(int category, const char *fmt, ...)
   180 {
   181     va_list ap;
   182 
   183     va_start(ap, fmt);
   184     SDL_LogMessageV(category, SDL_LOG_PRIORITY_VERBOSE, fmt, ap);
   185     va_end(ap);
   186 }
   187 
   188 void
   189 SDL_LogDebug(int category, const char *fmt, ...)
   190 {
   191     va_list ap;
   192 
   193     va_start(ap, fmt);
   194     SDL_LogMessageV(category, SDL_LOG_PRIORITY_DEBUG, fmt, ap);
   195     va_end(ap);
   196 }
   197 
   198 void
   199 SDL_LogInfo(int category, const char *fmt, ...)
   200 {
   201     va_list ap;
   202 
   203     va_start(ap, fmt);
   204     SDL_LogMessageV(category, SDL_LOG_PRIORITY_INFO, fmt, ap);
   205     va_end(ap);
   206 }
   207 
   208 void
   209 SDL_LogWarn(int category, const char *fmt, ...)
   210 {
   211     va_list ap;
   212 
   213     va_start(ap, fmt);
   214     SDL_LogMessageV(category, SDL_LOG_PRIORITY_WARN, fmt, ap);
   215     va_end(ap);
   216 }
   217 
   218 void
   219 SDL_LogError(int category, const char *fmt, ...)
   220 {
   221     va_list ap;
   222 
   223     va_start(ap, fmt);
   224     SDL_LogMessageV(category, SDL_LOG_PRIORITY_ERROR, fmt, ap);
   225     va_end(ap);
   226 }
   227 
   228 void
   229 SDL_LogCritical(int category, const char *fmt, ...)
   230 {
   231     va_list ap;
   232 
   233     va_start(ap, fmt);
   234     SDL_LogMessageV(category, SDL_LOG_PRIORITY_CRITICAL, fmt, ap);
   235     va_end(ap);
   236 }
   237 
   238 void
   239 SDL_LogMessage(int category, SDL_LogPriority priority, const char *fmt, ...)
   240 {
   241     va_list ap;
   242 
   243     va_start(ap, fmt);
   244     SDL_LogMessageV(category, priority, fmt, ap);
   245     va_end(ap);
   246 }
   247 
   248 #ifdef __ANDROID__
   249 static const char *
   250 GetCategoryPrefix(int category)
   251 {
   252     if (category < SDL_LOG_CATEGORY_RESERVED1) {
   253         return SDL_category_prefixes[category];
   254     }
   255     if (category < SDL_LOG_CATEGORY_CUSTOM) {
   256         return "RESERVED";
   257     }
   258     return "CUSTOM";
   259 }
   260 #endif /* __ANDROID__ */
   261 
   262 void
   263 SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list ap)
   264 {
   265     char *message;
   266 
   267     /* Nothing to do if we don't have an output function */
   268     if (!SDL_log_function) {
   269         return;
   270     }
   271 
   272     /* Make sure we don't exceed array bounds */
   273     if ((int)priority < 0 || priority >= SDL_NUM_LOG_PRIORITIES) {
   274         return;
   275     }
   276 
   277     /* See if we want to do anything with this message */
   278     if (priority < SDL_LogGetPriority(category)) {
   279         return;
   280     }
   281 
   282     message = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE);
   283     if (!message) {
   284         return;
   285     }
   286     SDL_vsnprintf(message, SDL_MAX_LOG_MESSAGE, fmt, ap);
   287     SDL_log_function(SDL_log_userdata, category, priority, message);
   288     SDL_stack_free(message);
   289 }
   290 
   291 static void
   292 SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
   293               const char *message)
   294 {
   295 #if defined(__WIN32__)
   296     /* Way too many allocations here, urgh */
   297     {
   298         char *output;
   299         size_t length;
   300         LPTSTR tstr;
   301 
   302         length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1;
   303         output = SDL_stack_alloc(char, length);
   304         SDL_snprintf(output, length, "%s: %s", SDL_priority_prefixes[priority], message);
   305         tstr = WIN_UTF8ToString(output);
   306         OutputDebugString(tstr);
   307         SDL_free(tstr);
   308         SDL_stack_free(output);
   309     }
   310 #elif defined(__ANDROID__)
   311     {
   312         char tag[32];
   313 
   314         SDL_snprintf(tag, SDL_arraysize(tag), "SDL/%s", GetCategoryPrefix(category));
   315         __android_log_write(SDL_android_priority[priority], tag, message);
   316     }
   317 #elif defined(__APPLE__)
   318     extern void SDL_NSLog(const char *text);
   319     {
   320         char *text;
   321 
   322         text = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE);
   323         if (text) {
   324             SDL_snprintf(text, SDL_MAX_LOG_MESSAGE, "%s: %s", SDL_priority_prefixes[priority], message);
   325             SDL_NSLog(text);
   326             SDL_stack_free(text);
   327             return;
   328         }
   329     }
   330 #elif defined(__PSP__)
   331 //Simple Log System for PSP
   332 	{
   333 		unsigned int length;
   334 		char*		 output;
   335 		FILE*		 pFile;
   336 		length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1;
   337         output = SDL_stack_alloc(char, length);
   338 		SDL_snprintf(output, length, "%s: %s", SDL_priority_prefixes[priority], message);
   339 		pFile = fopen ("SDL_Log.txt", "a");
   340 		fwrite (output, strlen (output), 1, pFile);
   341 		SDL_stack_free(output);
   342 		fclose (pFile);
   343 	}
   344 #endif
   345 #if HAVE_STDIO_H
   346     fprintf(stderr, "%s: %s\n", SDL_priority_prefixes[priority], message);
   347 #endif
   348 }
   349 
   350 void
   351 SDL_LogGetOutputFunction(SDL_LogOutputFunction *callback, void **userdata)
   352 {
   353     if (callback) {
   354         *callback = SDL_log_function;
   355     }
   356     if (userdata) {
   357         *userdata = SDL_log_userdata;
   358     }
   359 }
   360 
   361 void
   362 SDL_LogSetOutputFunction(SDL_LogOutputFunction callback, void *userdata)
   363 {
   364     SDL_log_function = callback;
   365     SDL_log_userdata = userdata;
   366 }
   367 
   368 /* vi: set ts=4 sw=4 expandtab: */