zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_log.c
Go to the documentation of this file.
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__)
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 /* Forward definition of error function */
43 extern int SDL_SetError(const char *fmt, ...);
44 
45 typedef 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 */
53 static void SDL_LogOutput(void *userdata,
54  int category, SDL_LogPriority priority,
55  const char *message);
56 
63 static void *SDL_log_userdata = NULL;
64 
66  NULL,
67  "VERBOSE",
68  "DEBUG",
69  "INFO",
70  "WARN",
71  "ERROR",
72  "CRITICAL"
73 };
74 
75 #ifdef __ANDROID__
76 static 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 
86 static 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 
98 void
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 
111 void
112 SDL_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 
134 SDL_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) {
148  } else if (category == SDL_LOG_CATEGORY_ASSERT) {
149  return SDL_assert_priority;
150  } else {
151  return SDL_default_priority;
152  }
153 }
154 
155 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 
170 }
171 
172 void
173 SDL_Log(const char *fmt, ...)
174 {
175  va_list ap;
176 
177  va_start(ap, fmt);
179  va_end(ap);
180 }
181 
182 void
183 SDL_LogVerbose(int category, 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 
192 void
193 SDL_LogDebug(int category, 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 
202 void
203 SDL_LogInfo(int category, 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 
212 void
213 SDL_LogWarn(int category, 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 
222 void
223 SDL_LogError(int category, 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 
232 void
233 SDL_LogCritical(int category, 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 
242 void
243 SDL_LogMessage(int category, SDL_LogPriority priority, 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__
253 static const char *
254 GetCategoryPrefix(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 
266 void
267 SDL_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 */
309 static int consoleAttached = 0;
310 
311 /* Handle to stderr output of console. */
312 static HANDLE stderrHandle = NULL;
313 #endif
314 
315 static void
316 SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
317  const char *message)
318 {
319 #if defined(__WIN32__)
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  BOOL attachResult;
327  DWORD attachError;
328  unsigned long charsWritten;
329 
330  /* Maybe attach console and get stderr handle */
331  if (consoleAttached == 0) {
332  attachResult = AttachConsole(ATTACH_PARENT_PROCESS);
333  if (!attachResult) {
334  attachError = GetLastError();
335  if (attachError == ERROR_INVALID_HANDLE) {
336  OutputDebugString(TEXT("Parent process has no console\r\n"));
337  consoleAttached = -1;
338  } else if (attachError == ERROR_GEN_FAILURE) {
339  OutputDebugString(TEXT("Could not attach to console of parent process\r\n"));
340  consoleAttached = -1;
341  } else if (attachError == ERROR_ACCESS_DENIED) {
342  /* Already attached */
343  consoleAttached = 1;
344  } else {
345  OutputDebugString(TEXT("Error attaching console\r\n"));
346  consoleAttached = -1;
347  }
348  } else {
349  /* Newly attached */
350  consoleAttached = 1;
351  }
352 
353  if (consoleAttached == 1) {
354  stderrHandle = GetStdHandle(STD_ERROR_HANDLE);
355  }
356  }
357 
358  length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1 + 1 + 1;
359  output = SDL_stack_alloc(char, length);
360  SDL_snprintf(output, length, "%s: %s\r\n", SDL_priority_prefixes[priority], message);
361  tstr = WIN_UTF8ToString(output);
362 
363  /* Output to debugger */
364  OutputDebugString(tstr);
365 
366  /* Screen output to stderr, if console was attached. */
367  if (consoleAttached == 1) {
368  if (!WriteConsole(stderrHandle, tstr, lstrlen(tstr), &charsWritten, NULL)) {
369  OutputDebugString(TEXT("Error calling WriteConsole\r\n"));
370  }
371  if (charsWritten == ERROR_NOT_ENOUGH_MEMORY) {
372  OutputDebugString(TEXT("Insufficient heap memory to write message\r\n"));
373  }
374  }
375 
376  SDL_free(tstr);
377  SDL_stack_free(output);
378  }
379 #elif defined(__ANDROID__)
380  {
381  char tag[32];
382 
383  SDL_snprintf(tag, SDL_arraysize(tag), "SDL/%s", GetCategoryPrefix(category));
384  __android_log_write(SDL_android_priority[priority], tag, message);
385  }
386 #elif defined(__APPLE__) && defined(SDL_VIDEO_DRIVER_COCOA)
387  /* Technically we don't need SDL_VIDEO_DRIVER_COCOA, but that's where this function is defined for now.
388  */
389  extern void SDL_NSLog(const char *text);
390  {
391  char *text;
392 
393  text = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE);
394  if (text) {
395  SDL_snprintf(text, SDL_MAX_LOG_MESSAGE, "%s: %s", SDL_priority_prefixes[priority], message);
396  SDL_NSLog(text);
397  SDL_stack_free(text);
398  return;
399  }
400  }
401 #elif defined(__PSP__)
402  {
403  FILE* pFile;
404  pFile = fopen ("SDL_Log.txt", "a");
405  fprintf(pFile, "%s: %s\n", SDL_priority_prefixes[priority], message);
406  fclose (pFile);
407  }
408 #endif
409 #if HAVE_STDIO_H
410  fprintf(stderr, "%s: %s\n", SDL_priority_prefixes[priority], message);
411 #endif
412 }
413 
414 void
416 {
417  if (callback) {
418  *callback = SDL_log_function;
419  }
420  if (userdata) {
421  *userdata = SDL_log_userdata;
422  }
423 }
424 
425 void
427 {
428  SDL_log_function = callback;
429  SDL_log_userdata = userdata;
430 }
431 
432 /* vi: set ts=4 sw=4 expandtab: */
#define DEFAULT_APPLICATION_PRIORITY
Definition: SDL_log.c:39
#define SDL_MAX_LOG_MESSAGE
The maximum size of a log message.
Definition: SDL_log.h:54
#define WIN_UTF8ToString(S)
Definition: SDL_windows.h:42
static SDL_LogPriority SDL_test_priority
Definition: SDL_log.c:61
static SDL_LogLevel * SDL_loglevels
Definition: SDL_log.c:57
GLsizei GLenum GLuint GLuint GLsizei GLchar * message
Definition: glew.h:2540
#define NULL
Definition: ftobjs.h:61
DECLSPEC int SDLCALL SDL_snprintf(char *text, size_t maxlen, const char *fmt,...)
Definition: SDL_string.c:1277
#define SDL_stack_free(data)
Definition: SDL_stdinc.h:227
#define DEFAULT_ASSERT_PRIORITY
Definition: SDL_log.c:38
DECLSPEC void SDLCALL SDL_LogSetAllPriority(SDL_LogPriority priority)
Set the priority of all log categories.
Definition: SDL_log.c:99
static const char * SDL_priority_prefixes[SDL_NUM_LOG_PRIORITIES]
Definition: SDL_log.c:65
DECLSPEC void SDLCALL SDL_free(void *mem)
DECLSPEC void SDLCALL SDL_LogResetPriorities(void)
Reset all priorities to default.
Definition: SDL_log.c:156
GLenum GLsizei len
Definition: glew.h:7035
DECLSPEC void SDLCALL SDL_LogCritical(int category, const char *fmt,...)
Log a message with SDL_LOG_PRIORITY_CRITICAL.
Definition: SDL_log.c:233
DECLSPEC void SDLCALL 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:267
typedef HANDLE(WINAPI *PFNWGLCREATEBUFFERREGIONARBPROC)(HDC hDC
static SDL_LogOutputFunction SDL_log_function
Definition: SDL_log.c:62
static SDL_LogPriority SDL_assert_priority
Definition: SDL_log.c:59
GLsizei GLsizei * length
Definition: gl2ext.h:792
DECLSPEC void SDLCALL SDL_LogDebug(int category, const char *fmt,...)
Log a message with SDL_LOG_PRIORITY_DEBUG.
Definition: SDL_log.c:193
static SDL_LogPriority SDL_default_priority
Definition: SDL_log.c:58
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
DECLSPEC void SDLCALL SDL_LogSetPriority(int category, SDL_LogPriority priority)
Set the priority of a particular log category.
Definition: SDL_log.c:112
DECLSPEC int SDLCALL SDL_SetError(const char *fmt,...)
Definition: SDL_error.c:53
DECLSPEC void *SDLCALL SDL_malloc(size_t size)
SDL_LogPriority
The predefined log priorities.
Definition: SDL_log.h:102
DECLSPEC void SDLCALL 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:426
DECLSPEC SDL_LogPriority SDLCALL SDL_LogGetPriority(int category)
Get the priority of a particular log category.
Definition: SDL_log.c:134
static void * SDL_log_userdata
Definition: SDL_log.c:63
DECLSPEC size_t SDLCALL SDL_strlen(const char *str)
Definition: SDL_string.c:389
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:83
DECLSPEC void SDLCALL SDL_Log(const char *fmt,...)
Log a message with SDL_LOG_CATEGORY_APPLICATION and SDL_LOG_PRIORITY_INFO.
Definition: SDL_log.c:173
DECLSPEC void SDLCALL SDL_LogVerbose(int category, const char *fmt,...)
Log a message with SDL_LOG_PRIORITY_VERBOSE.
Definition: SDL_log.c:183
typedef DWORD(WINAPI *XInputGetState_t)(DWORD dwUserIndex
DECLSPEC void SDLCALL SDL_LogError(int category, const char *fmt,...)
Log a message with SDL_LOG_PRIORITY_ERROR.
Definition: SDL_log.c:223
DECLSPEC void SDLCALL SDL_LogMessage(int category, SDL_LogPriority priority, const char *fmt,...)
Log a message with the specified category and priority.
Definition: SDL_log.c:243
DECLSPEC void SDLCALL SDL_LogWarn(int category, const char *fmt,...)
Log a message with SDL_LOG_PRIORITY_WARN.
Definition: SDL_log.c:213
DECLSPEC void SDLCALL SDL_LogGetOutputFunction(SDL_LogOutputFunction *callback, void **userdata)
Get the current log output function.
Definition: SDL_log.c:415
#define SDL_stack_alloc(type, count)
Definition: SDL_stdinc.h:226
#define DEFAULT_PRIORITY
Definition: SDL_log.c:37
static SDL_LogPriority SDL_application_priority
Definition: SDL_log.c:60
struct SDL_LogLevel SDL_LogLevel
#define DEFAULT_TEST_PRIORITY
Definition: SDL_log.c:40
DECLSPEC void SDLCALL SDL_LogInfo(int category, const char *fmt,...)
Log a message with SDL_LOG_PRIORITY_INFO.
Definition: SDL_log.c:203
static void SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority, const char *message)
Definition: SDL_log.c:316
DECLSPEC int SDLCALL SDL_vsnprintf(char *text, size_t maxlen, const char *fmt, va_list ap)
Definition: SDL_string.c:1479
typedef BOOL(WINAPI *PFNWGLSETSTEREOEMITTERSTATE3DLPROC)(HDC hDC