SDL 2.0
SDL_log.c
Go to the documentation of this file.
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2019 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__)
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{
51
52/* The default log output function */
53static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority, const char *message);
54
61static void *SDL_log_userdata = NULL;
62
64 NULL,
65 "VERBOSE",
66 "DEBUG",
67 "INFO",
68 "WARN",
69 "ERROR",
70 "CRITICAL"
71};
72
73#ifdef __ANDROID__
74static const char *SDL_category_prefixes[SDL_LOG_CATEGORY_RESERVED1] = {
75 "APP",
76 "ERROR",
77 "SYSTEM",
78 "AUDIO",
79 "VIDEO",
80 "RENDER",
81 "INPUT"
82};
83
84static int SDL_android_priority[SDL_NUM_LOG_PRIORITIES] = {
85 ANDROID_LOG_UNKNOWN,
86 ANDROID_LOG_VERBOSE,
87 ANDROID_LOG_DEBUG,
88 ANDROID_LOG_INFO,
89 ANDROID_LOG_WARN,
90 ANDROID_LOG_ERROR,
91 ANDROID_LOG_FATAL
92};
93#endif /* __ANDROID__ */
94
95
96void
98{
99 SDL_LogLevel *entry;
100
101 for (entry = SDL_loglevels; entry; entry = entry->next) {
102 entry->priority = priority;
103 }
107}
108
109void
111{
112 SDL_LogLevel *entry;
113
114 for (entry = SDL_loglevels; entry; entry = entry->next) {
115 if (entry->category == category) {
116 entry->priority = priority;
117 return;
118 }
119 }
120
121 /* Create a new entry */
122 entry = (SDL_LogLevel *)SDL_malloc(sizeof(*entry));
123 if (entry) {
124 entry->category = category;
125 entry->priority = priority;
126 entry->next = SDL_loglevels;
127 SDL_loglevels = entry;
128 }
129}
130
133{
134 SDL_LogLevel *entry;
135
136 for (entry = SDL_loglevels; entry; entry = entry->next) {
137 if (entry->category == category) {
138 return entry->priority;
139 }
140 }
141
143 return SDL_test_priority;
146 } else if (category == SDL_LOG_CATEGORY_ASSERT) {
147 return SDL_assert_priority;
148 } else {
150 }
151}
152
153void
155{
156 SDL_LogLevel *entry;
157
158 while (SDL_loglevels) {
159 entry = SDL_loglevels;
160 SDL_loglevels = entry->next;
161 SDL_free(entry);
162 }
163
168}
169
170void
172{
173 va_list ap;
174
175 va_start(ap, fmt);
177 va_end(ap);
178}
179
180void
182{
183 va_list ap;
184
185 va_start(ap, fmt);
187 va_end(ap);
188}
189
190void
192{
193 va_list ap;
194
195 va_start(ap, fmt);
197 va_end(ap);
198}
199
200void
202{
203 va_list ap;
204
205 va_start(ap, fmt);
207 va_end(ap);
208}
209
210void
212{
213 va_list ap;
214
215 va_start(ap, fmt);
217 va_end(ap);
218}
219
220void
222{
223 va_list ap;
224
225 va_start(ap, fmt);
227 va_end(ap);
228}
229
230void
232{
233 va_list ap;
234
235 va_start(ap, fmt);
237 va_end(ap);
238}
239
240void
242{
243 va_list ap;
244
245 va_start(ap, fmt);
247 va_end(ap);
248}
249
250#ifdef __ANDROID__
251static const char *
252GetCategoryPrefix(int category)
253{
255 return SDL_category_prefixes[category];
256 }
258 return "RESERVED";
259 }
260 return "CUSTOM";
261}
262#endif /* __ANDROID__ */
263
264void
265SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list ap)
266{
267 char *message;
268 size_t len;
269
270 /* Nothing to do if we don't have an output function */
271 if (!SDL_log_function) {
272 return;
273 }
274
275 /* Make sure we don't exceed array bounds */
276 if ((int)priority < 0 || priority >= SDL_NUM_LOG_PRIORITIES) {
277 return;
278 }
279
280 /* See if we want to do anything with this message */
282 return;
283 }
284
285 /* !!! FIXME: why not just "char message[SDL_MAX_LOG_MESSAGE];" ? */
287 if (!message) {
288 return;
289 }
290
292
293 /* Chop off final endline. */
295 if ((len > 0) && (message[len-1] == '\n')) {
296 message[--len] = '\0';
297 if ((len > 0) && (message[len-1] == '\r')) { /* catch "\r\n", too. */
298 message[--len] = '\0';
299 }
300 }
301
304}
305
306#if defined(__WIN32__) && !defined(HAVE_STDIO_H) && !defined(__WINRT__)
307/* Flag tracking the attachment of the console: 0=unattached, 1=attached to a console, 2=attached to a file, -1=error */
308static int consoleAttached = 0;
309
310/* Handle to stderr output of console. */
311static HANDLE stderrHandle = NULL;
312#endif
313
314static void SDLCALL
316 const char *message)
317{
318#if defined(__WIN32__) || defined(__WINRT__)
319 /* Way too many allocations here, urgh */
320 /* Note: One can't call SDL_SetError here, since that function itself logs. */
321 {
322 char *output;
323 size_t length;
324 LPTSTR tstr;
325 SDL_bool isstack;
326
327#if !defined(HAVE_STDIO_H) && !defined(__WINRT__)
328 BOOL attachResult;
329 DWORD attachError;
330 unsigned long charsWritten;
331 DWORD consoleMode;
332
333 /* Maybe attach console and get stderr handle */
334 if (consoleAttached == 0) {
335 attachResult = AttachConsole(ATTACH_PARENT_PROCESS);
336 if (!attachResult) {
337 attachError = GetLastError();
338 if (attachError == ERROR_INVALID_HANDLE) {
339 /* This is expected when running from Visual Studio */
340 /*OutputDebugString(TEXT("Parent process has no console\r\n"));*/
341 consoleAttached = -1;
342 } else if (attachError == ERROR_GEN_FAILURE) {
343 OutputDebugString(TEXT("Could not attach to console of parent process\r\n"));
344 consoleAttached = -1;
345 } else if (attachError == ERROR_ACCESS_DENIED) {
346 /* Already attached */
347 consoleAttached = 1;
348 } else {
349 OutputDebugString(TEXT("Error attaching console\r\n"));
350 consoleAttached = -1;
351 }
352 } else {
353 /* Newly attached */
354 consoleAttached = 1;
355 }
356
357 if (consoleAttached == 1) {
358 stderrHandle = GetStdHandle(STD_ERROR_HANDLE);
359
360 if (GetConsoleMode(stderrHandle, &consoleMode) == 0) {
361 /* WriteConsole fails if the output is redirected to a file. Must use WriteFile instead. */
362 consoleAttached = 2;
363 }
364 }
365 }
366#endif /* !defined(HAVE_STDIO_H) && !defined(__WINRT__) */
367
369 output = SDL_small_alloc(char, length, &isstack);
371 tstr = WIN_UTF8ToString(output);
372
373 /* Output to debugger */
374 OutputDebugString(tstr);
375
376#if !defined(HAVE_STDIO_H) && !defined(__WINRT__)
377 /* Screen output to stderr, if console was attached. */
378 if (consoleAttached == 1) {
379 if (!WriteConsole(stderrHandle, tstr, lstrlen(tstr), &charsWritten, NULL)) {
380 OutputDebugString(TEXT("Error calling WriteConsole\r\n"));
381 if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY) {
382 OutputDebugString(TEXT("Insufficient heap memory to write message\r\n"));
383 }
384 }
385
386 } else if (consoleAttached == 2) {
387 if (!WriteFile(stderrHandle, output, lstrlenA(output), &charsWritten, NULL)) {
388 OutputDebugString(TEXT("Error calling WriteFile\r\n"));
389 }
390 }
391#endif /* !defined(HAVE_STDIO_H) && !defined(__WINRT__) */
392
393 SDL_free(tstr);
394 SDL_small_free(output, isstack);
395 }
396#elif defined(__ANDROID__)
397 {
398 char tag[32];
399
400 SDL_snprintf(tag, SDL_arraysize(tag), "SDL/%s", GetCategoryPrefix(category));
401 __android_log_write(SDL_android_priority[priority], tag, message);
402 }
403#elif defined(__APPLE__) && (defined(SDL_VIDEO_DRIVER_COCOA) || defined(SDL_VIDEO_DRIVER_UIKIT))
404 /* Technically we don't need Cocoa/UIKit, but that's where this function is defined for now.
405 */
406 extern void SDL_NSLog(const char *text);
407 {
408 char *text;
409 /* !!! FIXME: why not just "char text[SDL_MAX_LOG_MESSAGE];" ? */
411 if (text) {
413 SDL_NSLog(text);
415 return;
416 }
417 }
418#elif defined(__PSP__)
419 {
420 FILE* pFile;
421 pFile = fopen ("SDL_Log.txt", "a");
422 fprintf(pFile, "%s: %s\n", SDL_priority_prefixes[priority], message);
423 fclose (pFile);
424 }
425#endif
426#if HAVE_STDIO_H
427 fprintf(stderr, "%s: %s\n", SDL_priority_prefixes[priority], message);
428#if __NACL__
429 fflush(stderr);
430#endif
431#endif
432}
433
434void
436{
437 if (callback) {
439 }
440 if (userdata) {
441 *userdata = SDL_log_userdata;
442 }
443}
444
445void
447{
449 SDL_log_userdata = userdata;
450}
451
452/* vi: set ts=4 sw=4 expandtab: */
#define SDL_malloc
#define SDL_strlen
#define SDL_free
#define SDL_vsnprintf
#define SDL_snprintf
#define SDLCALL
Definition: SDL_internal.h:49
#define SDL_small_alloc(type, count, pisstack)
Definition: SDL_internal.h:39
#define SDL_small_free(ptr, isstack)
Definition: SDL_internal.h:40
void SDL_LogSetOutputFunction(SDL_LogOutputFunction callback, void *userdata)
This function allows you to replace the default log output function with one of your own.
Definition: SDL_log.c:446
static SDL_LogPriority SDL_application_priority
Definition: SDL_log.c:58
#define DEFAULT_PRIORITY
Definition: SDL_log.c:40
SDL_LogPriority SDL_LogGetPriority(int category)
Get the priority of a particular log category.
Definition: SDL_log.c:132
static void * SDL_log_userdata
Definition: SDL_log.c:61
void SDL_LogSetPriority(int category, SDL_LogPriority priority)
Set the priority of a particular log category.
Definition: SDL_log.c:110
void SDL_LogGetOutputFunction(SDL_LogOutputFunction *callback, void **userdata)
Get the current log output function.
Definition: SDL_log.c:435
void SDL_Log(SDL_PRINTF_FORMAT_STRING const char *fmt,...)
Log a message with SDL_LOG_CATEGORY_APPLICATION and SDL_LOG_PRIORITY_INFO.
Definition: SDL_log.c:171
void SDL_LogSetAllPriority(SDL_LogPriority priority)
Set the priority of all log categories.
Definition: SDL_log.c:97
void SDL_LogResetPriorities(void)
Reset all priorities to default.
Definition: SDL_log.c:154
#define DEFAULT_ASSERT_PRIORITY
Definition: SDL_log.c:41
void SDL_LogWarn(int category, SDL_PRINTF_FORMAT_STRING const char *fmt,...)
Log a message with SDL_LOG_PRIORITY_WARN.
Definition: SDL_log.c:211
void SDL_LogInfo(int category, SDL_PRINTF_FORMAT_STRING const char *fmt,...)
Log a message with SDL_LOG_PRIORITY_INFO.
Definition: SDL_log.c:201
static SDL_LogLevel * SDL_loglevels
Definition: SDL_log.c:55
void SDL_LogError(int category, SDL_PRINTF_FORMAT_STRING const char *fmt,...)
Log a message with SDL_LOG_PRIORITY_ERROR.
Definition: SDL_log.c:221
void SDL_LogVerbose(int category, SDL_PRINTF_FORMAT_STRING const char *fmt,...)
Log a message with SDL_LOG_PRIORITY_VERBOSE.
Definition: SDL_log.c:181
static SDL_LogPriority SDL_default_priority
Definition: SDL_log.c:56
void SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list ap)
Log a message with the specified category and priority.
Definition: SDL_log.c:265
static void SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority, const char *message)
Definition: SDL_log.c:315
void SDL_LogCritical(int category, SDL_PRINTF_FORMAT_STRING const char *fmt,...)
Log a message with SDL_LOG_PRIORITY_CRITICAL.
Definition: SDL_log.c:231
static const char * SDL_priority_prefixes[SDL_NUM_LOG_PRIORITIES]
Definition: SDL_log.c:63
static SDL_LogPriority SDL_assert_priority
Definition: SDL_log.c:57
#define DEFAULT_APPLICATION_PRIORITY
Definition: SDL_log.c:42
static SDL_LogOutputFunction SDL_log_function
Definition: SDL_log.c:60
#define DEFAULT_TEST_PRIORITY
Definition: SDL_log.c:43
void SDL_LogDebug(int category, SDL_PRINTF_FORMAT_STRING const char *fmt,...)
Log a message with SDL_LOG_PRIORITY_DEBUG.
Definition: SDL_log.c:191
void SDL_LogMessage(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_STRING const char *fmt,...)
Log a message with the specified category and priority.
Definition: SDL_log.c:241
static SDL_LogPriority SDL_test_priority
Definition: SDL_log.c:59
#define SDL_MAX_LOG_MESSAGE
The maximum size of a log message.
Definition: SDL_log.h:54
SDL_LogPriority
The predefined log priorities.
Definition: SDL_log.h:103
@ SDL_NUM_LOG_PRIORITIES
Definition: SDL_log.h:110
@ SDL_LOG_PRIORITY_INFO
Definition: SDL_log.h:106
@ SDL_LOG_PRIORITY_CRITICAL
Definition: SDL_log.h:109
@ SDL_LOG_PRIORITY_VERBOSE
Definition: SDL_log.h:104
@ SDL_LOG_PRIORITY_DEBUG
Definition: SDL_log.h:105
@ SDL_LOG_PRIORITY_ERROR
Definition: SDL_log.h:108
@ SDL_LOG_PRIORITY_WARN
Definition: SDL_log.h:107
void(* SDL_LogOutputFunction)(void *userdata, int category, SDL_LogPriority priority, const char *message)
The prototype for the log output function.
Definition: SDL_log.h:189
@ SDL_LOG_CATEGORY_CUSTOM
Definition: SDL_log.h:96
@ SDL_LOG_CATEGORY_RESERVED1
Definition: SDL_log.h:77
@ SDL_LOG_CATEGORY_TEST
Definition: SDL_log.h:74
@ SDL_LOG_CATEGORY_APPLICATION
Definition: SDL_log.h:66
@ SDL_LOG_CATEGORY_ASSERT
Definition: SDL_log.h:68
GLenum GLsizei len
GLuint GLsizei const GLchar * message
GLuint GLsizei GLsizei * length
SDL_bool
Definition: SDL_stdinc.h:162
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
#define SDL_stack_alloc(type, count)
Definition: SDL_stdinc.h:354
#define SDL_PRINTF_FORMAT_STRING
Definition: SDL_stdinc.h:300
#define SDL_stack_free(data)
Definition: SDL_stdinc.h:355
#define WIN_UTF8ToString(S)
Definition: SDL_windows.h:47
#define NULL
Definition: begin_code.h:167
SDL_LogPriority priority
Definition: SDL_log.c:48
struct SDL_LogLevel * next
Definition: SDL_log.c:49
int category
Definition: SDL_log.c:47
static char text[MAX_TEXT_LENGTH]
Definition: testime.c:47
static Uint32 callback(Uint32 interval, void *param)
Definition: testtimer.c:34