[SDL_Tizen] Load 'libwayland-egl.so' using dlopen.
[platform/upstream/SDL.git] / src / SDL_log.c
1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2016 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__)
24 #include "core/windows/SDL_windows.h"
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 #ifndef __TIZEN__
41 #define __TIZEN__
42 #endif
43
44 #if defined(__TIZEN__)
45 #include <dlog/dlog.h>
46 #ifdef LOG_TAG
47 #undef LOG_TAG
48 #endif
49 #define LOG_TAG "SDL_LOG"
50 #define _SECURE_LOG
51 #endif
52
53
54
55 #define DEFAULT_PRIORITY                SDL_LOG_PRIORITY_CRITICAL
56 #define DEFAULT_ASSERT_PRIORITY         SDL_LOG_PRIORITY_WARN
57 #define DEFAULT_APPLICATION_PRIORITY    SDL_LOG_PRIORITY_INFO
58 #define DEFAULT_TEST_PRIORITY           SDL_LOG_PRIORITY_VERBOSE
59
60 typedef struct SDL_LogLevel
61 {
62     int category;
63     SDL_LogPriority priority;
64     struct SDL_LogLevel *next;
65 } SDL_LogLevel;
66
67 /* The default log output function */
68 static void SDL_LogOutput(void *userdata,
69                           int category, SDL_LogPriority priority,
70                           const char *message);
71
72 static SDL_LogLevel *SDL_loglevels;
73 static SDL_LogPriority SDL_default_priority = DEFAULT_PRIORITY;
74 static SDL_LogPriority SDL_assert_priority = DEFAULT_ASSERT_PRIORITY;
75 static SDL_LogPriority SDL_application_priority = DEFAULT_APPLICATION_PRIORITY;
76 static SDL_LogPriority SDL_test_priority = DEFAULT_TEST_PRIORITY;
77 static SDL_LogOutputFunction SDL_log_function = SDL_LogOutput;
78 static void *SDL_log_userdata = NULL;
79
80 static const char *SDL_priority_prefixes[SDL_NUM_LOG_PRIORITIES] = {
81     NULL,
82     "VERBOSE",
83     "DEBUG",
84     "INFO",
85     "WARN",
86     "ERROR",
87     "CRITICAL"
88 };
89
90 #if defined(__TIZEN__)
91 static const int SDL_dlog_debug_priority[SDL_NUM_LOG_PRIORITIES] = {
92     NULL,
93     DLOG_VERBOSE,
94     DLOG_DEBUG,
95     DLOG_INFO,
96     DLOG_WARN,
97     DLOG_ERROR,
98     DLOG_FATAL
99 };
100 #endif
101
102 #ifdef __ANDROID__
103 static const char *SDL_category_prefixes[SDL_LOG_CATEGORY_RESERVED1] = {
104     "APP",
105     "ERROR",
106     "SYSTEM",
107     "AUDIO",
108     "VIDEO",
109     "RENDER",
110     "INPUT"
111 };
112
113 static int SDL_android_priority[SDL_NUM_LOG_PRIORITIES] = {
114     ANDROID_LOG_UNKNOWN,
115     ANDROID_LOG_VERBOSE,
116     ANDROID_LOG_DEBUG,
117     ANDROID_LOG_INFO,
118     ANDROID_LOG_WARN,
119     ANDROID_LOG_ERROR,
120     ANDROID_LOG_FATAL
121 };
122 #endif /* __ANDROID__ */
123
124
125 void
126 SDL_LogSetAllPriority(SDL_LogPriority priority)
127 {
128     SDL_LogLevel *entry;
129
130     for (entry = SDL_loglevels; entry; entry = entry->next) {
131         entry->priority = priority;
132     }
133     SDL_default_priority = priority;
134     SDL_assert_priority = priority;
135     SDL_application_priority = priority;
136 }
137
138 void
139 SDL_LogSetPriority(int category, SDL_LogPriority priority)
140 {
141     SDL_LogLevel *entry;
142
143     for (entry = SDL_loglevels; entry; entry = entry->next) {
144         if (entry->category == category) {
145             entry->priority = priority;
146             return;
147         }
148     }
149
150     /* Create a new entry */
151     entry = (SDL_LogLevel *)SDL_malloc(sizeof(*entry));
152     if (entry) {
153         entry->category = category;
154         entry->priority = priority;
155         entry->next = SDL_loglevels;
156         SDL_loglevels = entry;
157     }
158 }
159
160 SDL_LogPriority
161 SDL_LogGetPriority(int category)
162 {
163     SDL_LogLevel *entry;
164
165     for (entry = SDL_loglevels; entry; entry = entry->next) {
166         if (entry->category == category) {
167             return entry->priority;
168         }
169     }
170
171     if (category == SDL_LOG_CATEGORY_TEST) {
172         return SDL_test_priority;
173     } else if (category == SDL_LOG_CATEGORY_APPLICATION) {
174         return SDL_application_priority;
175     } else if (category == SDL_LOG_CATEGORY_ASSERT) {
176         return SDL_assert_priority;
177     } else {
178         return SDL_default_priority;
179     }
180 }
181
182 void
183 SDL_LogResetPriorities(void)
184 {
185     SDL_LogLevel *entry;
186
187     while (SDL_loglevels) {
188         entry = SDL_loglevels;
189         SDL_loglevels = entry->next;
190         SDL_free(entry);
191     }
192
193     SDL_default_priority = DEFAULT_PRIORITY;
194     SDL_assert_priority = DEFAULT_ASSERT_PRIORITY;
195     SDL_application_priority = DEFAULT_APPLICATION_PRIORITY;
196     SDL_test_priority = DEFAULT_TEST_PRIORITY;
197 }
198
199 void
200 SDL_Log(SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
201 {
202     va_list ap;
203
204     va_start(ap, fmt);
205     SDL_LogMessageV(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, fmt, ap);
206     va_end(ap);
207 }
208
209 void
210 SDL_LogVerbose(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
211 {
212     va_list ap;
213
214     va_start(ap, fmt);
215     SDL_LogMessageV(category, SDL_LOG_PRIORITY_VERBOSE, fmt, ap);
216     va_end(ap);
217 }
218
219 void
220 SDL_LogDebug(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
221 {
222     va_list ap;
223
224     va_start(ap, fmt);
225     SDL_LogMessageV(category, SDL_LOG_PRIORITY_DEBUG, fmt, ap);
226     va_end(ap);
227 }
228
229 void
230 SDL_LogInfo(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
231 {
232     va_list ap;
233
234     va_start(ap, fmt);
235     SDL_LogMessageV(category, SDL_LOG_PRIORITY_INFO, fmt, ap);
236     va_end(ap);
237 }
238
239 void
240 SDL_LogWarn(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
241 {
242     va_list ap;
243
244     va_start(ap, fmt);
245     SDL_LogMessageV(category, SDL_LOG_PRIORITY_WARN, fmt, ap);
246     va_end(ap);
247 }
248
249 void
250 SDL_LogError(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
251 {
252     va_list ap;
253
254     va_start(ap, fmt);
255     SDL_LogMessageV(category, SDL_LOG_PRIORITY_ERROR, fmt, ap);
256     va_end(ap);
257 }
258
259 void
260 SDL_LogCritical(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
261 {
262     va_list ap;
263
264     va_start(ap, fmt);
265     SDL_LogMessageV(category, SDL_LOG_PRIORITY_CRITICAL, fmt, ap);
266     va_end(ap);
267 }
268
269 void
270 SDL_LogMessage(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
271 {
272     va_list ap;
273
274     va_start(ap, fmt);
275     SDL_LogMessageV(category, priority, fmt, ap);
276     va_end(ap);
277 }
278
279 #ifdef __ANDROID__
280 static const char *
281 GetCategoryPrefix(int category)
282 {
283     if (category < SDL_LOG_CATEGORY_RESERVED1) {
284         return SDL_category_prefixes[category];
285     }
286     if (category < SDL_LOG_CATEGORY_CUSTOM) {
287         return "RESERVED";
288     }
289     return "CUSTOM";
290 }
291 #endif /* __ANDROID__ */
292
293 void
294 SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list ap)
295 {
296     char *message;
297     size_t len;
298
299     /* Nothing to do if we don't have an output function */
300     if (!SDL_log_function) {
301         return;
302     }
303
304     /* Make sure we don't exceed array bounds */
305     if ((int)priority < 0 || priority >= SDL_NUM_LOG_PRIORITIES) {
306         return;
307     }
308
309     /* See if we want to do anything with this message */
310     if (priority < SDL_LogGetPriority(category)) {
311         return;
312     }
313
314     message = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE);
315     if (!message) {
316         return;
317     }
318
319     SDL_vsnprintf(message, SDL_MAX_LOG_MESSAGE, fmt, ap);
320
321     /* Chop off final endline. */
322     len = SDL_strlen(message);
323     if ((len > 0) && (message[len-1] == '\n')) {
324         message[--len] = '\0';
325         if ((len > 0) && (message[len-1] == '\r')) {  /* catch "\r\n", too. */
326             message[--len] = '\0';
327         }
328     }
329
330     SDL_log_function(SDL_log_userdata, category, priority, message);
331     SDL_stack_free(message);
332 }
333
334 #if defined(__WIN32__)
335 /* Flag tracking the attachment of the console: 0=unattached, 1=attached, -1=error */
336 static int consoleAttached = 0;
337
338 /* Handle to stderr output of console. */
339 static HANDLE stderrHandle = NULL;
340 #endif
341
342 #if defined(__TIZEN__)
343 static void
344 SDL_PrintDlog(int priority, char *format, ...)
345 {
346     va_list ap;
347
348     if (priority >= SDL_NUM_LOG_PRIORITIES)
349         return;
350
351     va_start(ap, format);
352     dlog_vprint(SDL_dlog_debug_priority[priority], LOG_TAG, format, ap);
353     va_end(ap);
354 }
355 #endif
356
357 static void
358 SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
359               const char *message)
360 {
361 #if defined(__WIN32__) || defined(__WINRT__)
362     /* Way too many allocations here, urgh */
363     /* Note: One can't call SDL_SetError here, since that function itself logs. */
364     {
365         char *output;
366         size_t length;
367         LPTSTR tstr;
368
369 #ifndef __WINRT__
370         BOOL attachResult;
371         DWORD attachError;
372         unsigned long charsWritten; 
373
374         /* Maybe attach console and get stderr handle */
375         if (consoleAttached == 0) {
376             attachResult = AttachConsole(ATTACH_PARENT_PROCESS);
377             if (!attachResult) {
378                     attachError = GetLastError();
379                     if (attachError == ERROR_INVALID_HANDLE) {
380                         OutputDebugString(TEXT("Parent process has no console\r\n"));
381                         consoleAttached = -1;
382                     } else if (attachError == ERROR_GEN_FAILURE) {
383                          OutputDebugString(TEXT("Could not attach to console of parent process\r\n"));
384                          consoleAttached = -1;
385                     } else if (attachError == ERROR_ACCESS_DENIED) {  
386                          /* Already attached */
387                         consoleAttached = 1;
388                     } else {
389                         OutputDebugString(TEXT("Error attaching console\r\n"));
390                         consoleAttached = -1;
391                     }
392                 } else {
393                     /* Newly attached */
394                     consoleAttached = 1;
395                 }
396                         
397                 if (consoleAttached == 1) {
398                         stderrHandle = GetStdHandle(STD_ERROR_HANDLE);
399                 }
400         }
401 #endif /* ifndef __WINRT__ */
402
403         length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1 + 1 + 1;
404         output = SDL_stack_alloc(char, length);
405         SDL_snprintf(output, length, "%s: %s\r\n", SDL_priority_prefixes[priority], message);
406         tstr = WIN_UTF8ToString(output);
407         
408         /* Output to debugger */
409         OutputDebugString(tstr);
410        
411 #ifndef __WINRT__
412         /* Screen output to stderr, if console was attached. */
413         if (consoleAttached == 1) {
414                 if (!WriteConsole(stderrHandle, tstr, lstrlen(tstr), &charsWritten, NULL)) {
415                     OutputDebugString(TEXT("Error calling WriteConsole\r\n"));
416                     if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY) {
417                         OutputDebugString(TEXT("Insufficient heap memory to write message\r\n"));
418                     }
419                 }
420         }
421 #endif /* ifndef __WINRT__ */
422
423         SDL_free(tstr);
424         SDL_stack_free(output);
425     }
426 #elif defined(__ANDROID__)
427     {
428         char tag[32];
429
430         SDL_snprintf(tag, SDL_arraysize(tag), "SDL/%s", GetCategoryPrefix(category));
431         __android_log_write(SDL_android_priority[priority], tag, message);
432     }
433 #elif defined(__APPLE__) && defined(SDL_VIDEO_DRIVER_COCOA)
434     /* Technically we don't need SDL_VIDEO_DRIVER_COCOA, but that's where this function is defined for now.
435     */
436     extern void SDL_NSLog(const char *text);
437     {
438         char *text;
439
440         text = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE);
441         if (text) {
442             SDL_snprintf(text, SDL_MAX_LOG_MESSAGE, "%s: %s", SDL_priority_prefixes[priority], message);
443             SDL_NSLog(text);
444             SDL_stack_free(text);
445             return;
446         }
447     }
448 #elif defined(__PSP__)
449     {
450         FILE*        pFile;
451         pFile = fopen ("SDL_Log.txt", "a");
452         fprintf(pFile, "%s: %s\n", SDL_priority_prefixes[priority], message);
453         fclose (pFile);
454     }
455 #elif defined(__TIZEN__)
456     {
457         SDL_PrintDlog(priority, "%s: %s", SDL_priority_prefixes[priority], message);
458     }
459 #endif
460 #if HAVE_STDIO_H
461     fprintf(stderr, "%s: %s\n", SDL_priority_prefixes[priority], message);
462 #endif
463 #if __NACL__
464     fflush(stderr);
465 #endif
466 }
467
468 void
469 SDL_LogGetOutputFunction(SDL_LogOutputFunction *callback, void **userdata)
470 {
471     if (callback) {
472         *callback = SDL_log_function;
473     }
474     if (userdata) {
475         *userdata = SDL_log_userdata;
476     }
477 }
478
479 void
480 SDL_LogSetOutputFunction(SDL_LogOutputFunction callback, void *userdata)
481 {
482     SDL_log_function = callback;
483     SDL_log_userdata = userdata;
484 }
485
486 /* vi: set ts=4 sw=4 expandtab: */