aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/eina/src/lib/eina_log.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/eina/src/lib/eina_log.c')
-rw-r--r--libraries/eina/src/lib/eina_log.c1993
1 files changed, 0 insertions, 1993 deletions
diff --git a/libraries/eina/src/lib/eina_log.c b/libraries/eina/src/lib/eina_log.c
deleted file mode 100644
index 4e2bb6d..0000000
--- a/libraries/eina/src/lib/eina_log.c
+++ /dev/null
@@ -1,1993 +0,0 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2007-2009 Jorge Luis Zapata Muga, Cedric Bail, Andre Dieb
3 * Martins
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library;
17 * if not, see <http://www.gnu.org/licenses/>.
18 */
19
20#ifdef HAVE_CONFIG_H
21# include "config.h"
22#endif
23
24#include <stdio.h>
25#include <string.h>
26#include <stdlib.h>
27#include <fnmatch.h>
28#include <assert.h>
29#include <errno.h>
30
31#ifdef HAVE_UNISTD_H
32# include <unistd.h>
33#endif
34
35#ifdef EFL_HAVE_POSIX_THREADS
36# include <pthread.h>
37#endif
38
39#ifdef HAVE_EVIL
40# include <Evil.h>
41#endif
42
43#include "eina_config.h"
44#include "eina_private.h"
45#include "eina_inlist.h"
46
47/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
48#include "eina_safety_checks.h"
49#include "eina_log.h"
50
51/* TODO
52 * + printing logs to stdout or stderr can be implemented
53 * using a queue, useful for multiple threads printing
54 * + add a wrapper for assert?
55 */
56
57/*============================================================================*
58* Local *
59*============================================================================*/
60
61/**
62 * @cond LOCAL
63 */
64
65#define EINA_LOG_ENV_ABORT "EINA_LOG_ABORT"
66#define EINA_LOG_ENV_ABORT_LEVEL "EINA_LOG_ABORT_LEVEL"
67#define EINA_LOG_ENV_LEVEL "EINA_LOG_LEVEL"
68#define EINA_LOG_ENV_LEVELS "EINA_LOG_LEVELS"
69#define EINA_LOG_ENV_LEVELS_GLOB "EINA_LOG_LEVELS_GLOB"
70#define EINA_LOG_ENV_COLOR_DISABLE "EINA_LOG_COLOR_DISABLE"
71#define EINA_LOG_ENV_FILE_DISABLE "EINA_LOG_FILE_DISABLE"
72#define EINA_LOG_ENV_FUNCTION_DISABLE "EINA_LOG_FUNCTION_DISABLE"
73
74#ifdef EINA_ENABLE_LOG
75
76// Structure for storing domain level settings passed from the command line
77// that will be matched with application-defined domains.
78typedef struct _Eina_Log_Domain_Level_Pending Eina_Log_Domain_Level_Pending;
79struct _Eina_Log_Domain_Level_Pending
80{
81 EINA_INLIST;
82 unsigned int level;
83 size_t namelen;
84 char name[];
85};
86
87/*
88 * List of levels for domains set by the user before the domains are registered,
89 * updates the domain levels on the first log and clears itself.
90 */
91static Eina_Inlist *_pending_list = NULL;
92static Eina_Inlist *_glob_list = NULL;
93
94// Disable color flag (can be changed through the env var
95// EINA_LOG_ENV_COLOR_DISABLE).
96static Eina_Bool _disable_color = EINA_FALSE;
97static Eina_Bool _disable_file = EINA_FALSE;
98static Eina_Bool _disable_function = EINA_FALSE;
99static Eina_Bool _abort_on_critical = EINA_FALSE;
100static int _abort_level_on_critical = EINA_LOG_LEVEL_CRITICAL;
101
102#ifdef EFL_HAVE_THREADS
103
104static Eina_Bool _threads_enabled = EINA_FALSE;
105static Eina_Bool _threads_inited = EINA_FALSE;
106
107# ifdef EFL_HAVE_POSIX_THREADS
108
109typedef pthread_t Thread;
110
111static pthread_t _main_thread;
112
113# define SELF() pthread_self()
114# define IS_MAIN(t) pthread_equal(t, _main_thread)
115# define IS_OTHER(t) EINA_UNLIKELY(!IS_MAIN(t))
116# define CHECK_MAIN(...) \
117 do { \
118 if (!IS_MAIN(pthread_self())) { \
119 fprintf(stderr, \
120 "ERR: not main thread! current=%lu, main=%lu\n", \
121 (unsigned long)pthread_self(), \
122 (unsigned long)_main_thread); \
123 return __VA_ARGS__; \
124 } \
125 } while (0)
126
127# ifdef EFL_HAVE_POSIX_THREADS_SPINLOCK
128
129static pthread_spinlock_t _log_lock;
130
131static Eina_Bool _eina_log_spinlock_init(void)
132{
133 if (pthread_spin_init(&_log_lock, PTHREAD_PROCESS_PRIVATE) == 0)
134 return EINA_TRUE;
135
136 fprintf(stderr,
137 "ERROR: pthread_spin_init(%p, PTHREAD_PROCESS_PRIVATE): %s\n",
138 &_log_lock, strerror(errno));
139 return EINA_FALSE;
140}
141
142# define LOG_LOCK() \
143 if (_threads_enabled) \
144 do { \
145 if (0) { \
146 fprintf(stderr, "+++LOG LOG_LOCKED! [%s, %lu]\n", \
147 __FUNCTION__, (unsigned long)pthread_self()); } \
148 if (EINA_UNLIKELY(_threads_enabled)) { \
149 pthread_spin_lock(&_log_lock); } \
150 } while (0)
151# define LOG_UNLOCK() \
152 if (_threads_enabled) \
153 do { \
154 if (EINA_UNLIKELY(_threads_enabled)) { \
155 pthread_spin_unlock(&_log_lock); } \
156 if (0) { \
157 fprintf(stderr, \
158 "---LOG LOG_UNLOCKED! [%s, %lu]\n", \
159 __FUNCTION__, (unsigned long)pthread_self()); } \
160 } while (0)
161# define INIT() _eina_log_spinlock_init()
162# define SHUTDOWN() pthread_spin_destroy(&_log_lock)
163
164# else /* ! EFL_HAVE_POSIX_THREADS_SPINLOCK */
165
166static pthread_mutex_t _log_mutex = PTHREAD_MUTEX_INITIALIZER;
167# define LOG_LOCK() if(_threads_enabled) {pthread_mutex_lock(&_log_mutex); }
168# define LOG_UNLOCK() if(_threads_enabled) {pthread_mutex_unlock(&_log_mutex); }
169# define INIT() (1)
170# define SHUTDOWN() do {} while (0)
171
172# endif /* ! EFL_HAVE_POSIX_THREADS_SPINLOCK */
173
174# else /* EFL_HAVE_WIN32_THREADS */
175
176typedef DWORD Thread;
177
178static DWORD _main_thread;
179
180# define SELF() GetCurrentThreadId()
181# define IS_MAIN(t) (t == _main_thread)
182# define IS_OTHER(t) EINA_UNLIKELY(!IS_MAIN(t))
183# define CHECK_MAIN(...) \
184 do { \
185 if (!IS_MAIN(GetCurrentThreadId())) { \
186 fprintf(stderr, \
187 "ERR: not main thread! current=%lu, main=%lu\n", \
188 GetCurrentThreadId(), _main_thread); \
189 return __VA_ARGS__; \
190 } \
191 } while (0)
192
193static HANDLE _log_mutex = NULL;
194
195# define LOG_LOCK() if(_threads_enabled) WaitForSingleObject(_log_mutex, INFINITE)
196# define LOG_UNLOCK() if(_threads_enabled) ReleaseMutex(_log_mutex)
197# define INIT() ((_log_mutex = CreateMutex(NULL, FALSE, NULL)) ? 1 : 0)
198# define SHUTDOWN() if (_log_mutex) CloseHandle(_log_mutex)
199
200# endif /* EFL_HAVE_WIN32_THREADS */
201
202#else /* ! EFL_HAVE_THREADS */
203
204# define LOG_LOCK() do {} while (0)
205# define LOG_UNLOCK() do {} while (0)
206# define IS_MAIN(t) (1)
207# define IS_OTHER(t) (0)
208# define CHECK_MAIN(...) do {} while (0)
209# define INIT() (1)
210# define SHUTDOWN() do {} while (0)
211
212#endif /* ! EFL_HAVE_THREADS */
213
214
215// List of domains registered
216static Eina_Log_Domain *_log_domains = NULL;
217static unsigned int _log_domains_count = 0;
218static size_t _log_domains_allocated = 0;
219
220// Default function for printing on domains
221static Eina_Log_Print_Cb _print_cb = eina_log_print_cb_stderr;
222static void *_print_cb_data = NULL;
223
224#ifdef DEBUG
225static Eina_Log_Level _log_level = EINA_LOG_LEVEL_DBG;
226#elif DEBUG_CRITICAL
227static Eina_Log_Level _log_level = EINA_LOG_LEVEL_CRITICAL;
228#else
229static Eina_Log_Level _log_level = EINA_LOG_LEVEL_ERR;
230#endif
231
232/* NOTE: if you change this, also change:
233 * eina_log_print_level_name_get()
234 * eina_log_print_level_name_color_get()
235 */
236static const char *_names[] = {
237 "CRI",
238 "ERR",
239 "WRN",
240 "INF",
241 "DBG",
242};
243
244#ifdef _WIN32
245static int
246eina_log_win32_color_get(const char *domain_str)
247{
248 char *str;
249 char *tmp;
250 char *tmp2;
251 int code = -1;
252 int lighted = 0;
253 int ret = 0;
254
255 str = strdup(domain_str);
256 if (!str)
257 return 0;
258
259 /* this should not append */
260 if (str[0] != '\033')
261 {
262 free(str);
263 return 0;
264 }
265
266 /* we skip the first char and the [ */
267 tmp = tmp2 = str + 2;
268 while (*tmp != 'm')
269 {
270 if (*tmp == ';')
271 {
272 *tmp = '\0';
273 code = atol(tmp2);
274 tmp++;
275 tmp2 = tmp;
276 }
277
278 tmp++;
279 }
280 *tmp = '\0';
281 if (code < 0)
282 code = atol(tmp2);
283 else
284 lighted = atol(tmp2);
285
286 free(str);
287
288 if (code < lighted)
289 {
290 int c;
291
292 c = code;
293 code = lighted;
294 lighted = c;
295 }
296
297 if (lighted)
298 ret = FOREGROUND_INTENSITY;
299
300 if (code == 31)
301 ret |= FOREGROUND_RED;
302 else if (code == 32)
303 ret |= FOREGROUND_GREEN;
304 else if (code == 33)
305 ret |= FOREGROUND_RED | FOREGROUND_GREEN;
306 else if (code == 34)
307 ret |= FOREGROUND_BLUE;
308 else if (code == 36)
309 ret |= FOREGROUND_GREEN | FOREGROUND_BLUE;
310 else if (code == 37)
311 ret |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
312
313 return ret;
314}
315#endif
316
317static inline unsigned int
318eina_log_pid_get(void)
319{
320 return (unsigned int)getpid();
321}
322
323static inline void
324eina_log_print_level_name_get(int level, const char **p_name)
325{
326 static char buf[4];
327 /* NOTE: if you change this, also change
328 * eina_log_print_level_name_color_get()
329 * eina_log_level_name_get() (at eina_inline_log.x)
330 */
331 if (EINA_UNLIKELY(level < 0))
332 {
333 snprintf(buf, sizeof(buf), "%03d", level);
334 *p_name = buf;
335 }
336 else if (EINA_UNLIKELY(level >= EINA_LOG_LEVELS))
337 {
338 snprintf(buf, sizeof(buf), "%03d", level);
339 *p_name = buf;
340 }
341 else
342 *p_name = _names[level];
343}
344
345#ifdef _WIN32
346static inline void
347eina_log_print_level_name_color_get(int level,
348 const char **p_name,
349 int *p_color)
350{
351 static char buf[4];
352 /* NOTE: if you change this, also change:
353 * eina_log_print_level_name_get()
354 */
355 if (EINA_UNLIKELY(level < 0))
356 {
357 snprintf(buf, sizeof(buf), "%03d", level);
358 *p_name = buf;
359 }
360 else if (EINA_UNLIKELY(level >= EINA_LOG_LEVELS))
361 {
362 snprintf(buf, sizeof(buf), "%03d", level);
363 *p_name = buf;
364 }
365 else
366 *p_name = _names[level];
367
368 *p_color = eina_log_win32_color_get(eina_log_level_color_get(level));
369}
370#else
371static inline void
372eina_log_print_level_name_color_get(int level,
373 const char **p_name,
374 const char **p_color)
375{
376 static char buf[4];
377 /* NOTE: if you change this, also change:
378 * eina_log_print_level_name_get()
379 */
380 if (EINA_UNLIKELY(level < 0))
381 {
382 snprintf(buf, sizeof(buf), "%03d", level);
383 *p_name = buf;
384 }
385 else if (EINA_UNLIKELY(level >= EINA_LOG_LEVELS))
386 {
387 snprintf(buf, sizeof(buf), "%03d", level);
388 *p_name = buf;
389 }
390 else
391 *p_name = _names[level];
392
393 *p_color = eina_log_level_color_get(level);
394}
395#endif
396
397#define DECLARE_LEVEL_NAME(level) const char *name; \
398 eina_log_print_level_name_get(level, &name)
399#ifdef _WIN32
400# define DECLARE_LEVEL_NAME_COLOR(level) const char *name; int color; \
401 eina_log_print_level_name_color_get(level, &name, &color)
402#else
403# define DECLARE_LEVEL_NAME_COLOR(level) const char *name, *color; \
404 eina_log_print_level_name_color_get(level, &name, &color)
405#endif
406
407/** No threads, No color */
408static void
409eina_log_print_prefix_NOthreads_NOcolor_file_func(FILE *fp,
410 const Eina_Log_Domain *d,
411 Eina_Log_Level level,
412 const char *file,
413 const char *fnc,
414 int line)
415{
416 DECLARE_LEVEL_NAME(level);
417 fprintf(fp, "%s<%u>:%s %s:%d %s() ", name, eina_log_pid_get(),
418 d->domain_str, file, line, fnc);
419}
420
421static void
422eina_log_print_prefix_NOthreads_NOcolor_NOfile_func(FILE *fp,
423 const Eina_Log_Domain *d,
424 Eina_Log_Level level,
425 const char *file __UNUSED__,
426 const char *fnc,
427 int line __UNUSED__)
428{
429 DECLARE_LEVEL_NAME(level);
430 fprintf(fp, "%s<%u>:%s %s() ", name, eina_log_pid_get(), d->domain_str,
431 fnc);
432}
433
434static void
435eina_log_print_prefix_NOthreads_NOcolor_file_NOfunc(FILE *fp,
436 const Eina_Log_Domain *d,
437 Eina_Log_Level level,
438 const char *file,
439 const char *fnc __UNUSED__,
440 int line)
441{
442 DECLARE_LEVEL_NAME(level);
443 fprintf(fp, "%s<%u>:%s %s:%d ", name, eina_log_pid_get(), d->domain_str,
444 file, line);
445}
446
447/* No threads, color */
448static void
449eina_log_print_prefix_NOthreads_color_file_func(FILE *fp,
450 const Eina_Log_Domain *d,
451 Eina_Log_Level level,
452 const char *file,
453 const char *fnc,
454 int line)
455{
456 DECLARE_LEVEL_NAME_COLOR(level);
457#ifdef _WIN32_WCE
458 fprintf(fp, "%s<%u>:%s %s:%d %s() ", name, eina_log_pid_get(),
459 d->domain_str, file, line, fnc);
460#elif _WIN32
461 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
462 color);
463 fprintf(fp, "%s", name);
464 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
465 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
466 fprintf(fp, ":");
467 SetConsoleTextAttribute(GetStdHandle(
468 STD_OUTPUT_HANDLE),
469 eina_log_win32_color_get(d->domain_str));
470 fprintf(fp, "%s", d->name);
471 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
472 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
473 fprintf(fp, " %s:%d ", file, line);
474 SetConsoleTextAttribute(GetStdHandle(
475 STD_OUTPUT_HANDLE),
476 FOREGROUND_INTENSITY | FOREGROUND_RED |
477 FOREGROUND_GREEN | FOREGROUND_BLUE);
478 fprintf(fp, "%s()", fnc);
479 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
480 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
481 fprintf(fp, " ");
482#else
483 fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s %s:%d "
484 EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ",
485 color, name, eina_log_pid_get(), d->domain_str, file, line, fnc);
486#endif
487}
488
489static void
490eina_log_print_prefix_NOthreads_color_NOfile_func(FILE *fp,
491 const Eina_Log_Domain *d,
492 Eina_Log_Level level,
493 const char *file __UNUSED__,
494 const char *fnc,
495 int line __UNUSED__)
496{
497 DECLARE_LEVEL_NAME_COLOR(level);
498#ifdef _WIN32_WCE
499 fprintf(fp, "%s<%u>:%s %s() ", name, eina_log_pid_get(), d->domain_str,
500 fnc);
501#elif _WIN32
502 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
503 color);
504 fprintf(fp, "%s", name);
505 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
506 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
507 fprintf(fp, ":");
508 SetConsoleTextAttribute(GetStdHandle(
509 STD_OUTPUT_HANDLE),
510 eina_log_win32_color_get(d->domain_str));
511 fprintf(fp, "%s", d->name);
512 SetConsoleTextAttribute(GetStdHandle(
513 STD_OUTPUT_HANDLE),
514 FOREGROUND_INTENSITY | FOREGROUND_RED |
515 FOREGROUND_GREEN | FOREGROUND_BLUE);
516 fprintf(fp, "%s()", fnc);
517 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
518 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
519 fprintf(fp, " ");
520#else
521 fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s "
522 EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ",
523 color, name, eina_log_pid_get(), d->domain_str, fnc);
524#endif
525}
526
527static void
528eina_log_print_prefix_NOthreads_color_file_NOfunc(FILE *fp,
529 const Eina_Log_Domain *d,
530 Eina_Log_Level level,
531 const char *file,
532 const char *fnc __UNUSED__,
533 int line)
534{
535 DECLARE_LEVEL_NAME_COLOR(level);
536#ifdef _WIN32_WCE
537 fprintf(fp, "%s<%u>:%s %s:%d ", name, eina_log_pid_get(), d->domain_str,
538 file, line);
539#elif _WIN32
540 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
541 color);
542 fprintf(fp, "%s", name);
543 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
544 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
545 fprintf(fp, ":");
546 SetConsoleTextAttribute(GetStdHandle(
547 STD_OUTPUT_HANDLE),
548 eina_log_win32_color_get(d->domain_str));
549 fprintf(fp, "%s", d->name);
550 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
551 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
552 fprintf(fp, " %s:%d ", file, line);
553#else
554 fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s %s:%d ",
555 color, name, eina_log_pid_get(), d->domain_str, file, line);
556#endif
557}
558
559/** threads, No color */
560#ifdef EFL_HAVE_THREADS
561static void
562eina_log_print_prefix_threads_NOcolor_file_func(FILE *fp,
563 const Eina_Log_Domain *d,
564 Eina_Log_Level level,
565 const char *file,
566 const char *fnc,
567 int line)
568{
569 Thread cur;
570
571 DECLARE_LEVEL_NAME(level);
572 cur = SELF();
573 if (IS_OTHER(cur))
574 {
575 fprintf(fp, "%s<%u>:%s[T:%lu] %s:%d %s() ",
576 name, eina_log_pid_get(), d->domain_str,
577 (unsigned long)cur, file, line, fnc);
578 return;
579 }
580 fprintf(fp, "%s<%u>:%s %s:%d %s() ",
581 name, eina_log_pid_get(), d->domain_str, file, line, fnc);
582}
583
584static void
585eina_log_print_prefix_threads_NOcolor_NOfile_func(FILE *fp,
586 const Eina_Log_Domain *d,
587 Eina_Log_Level level,
588 const char *file __UNUSED__,
589 const char *fnc,
590 int line __UNUSED__)
591{
592 Thread cur;
593
594 DECLARE_LEVEL_NAME(level);
595 cur = SELF();
596 if (IS_OTHER(cur))
597 {
598 fprintf(fp, "%s<%u>:%s[T:%lu] %s() ",
599 name, eina_log_pid_get(), d->domain_str,
600 (unsigned long)cur, fnc);
601 return;
602 }
603 fprintf(fp, "%s<%u>:%s %s() ",
604 name, eina_log_pid_get(), d->domain_str, fnc);
605}
606
607static void
608eina_log_print_prefix_threads_NOcolor_file_NOfunc(FILE *fp,
609 const Eina_Log_Domain *d,
610 Eina_Log_Level level,
611 const char *file,
612 const char *fnc __UNUSED__,
613 int line)
614{
615 Thread cur;
616
617 DECLARE_LEVEL_NAME(level);
618 cur = SELF();
619 if (IS_OTHER(cur))
620 {
621 fprintf(fp, "%s<%u>:%s[T:%lu] %s:%d ",
622 name, eina_log_pid_get(), d->domain_str, (unsigned long)cur,
623 file, line);
624 return;
625 }
626
627 fprintf(fp, "%s<%u>:%s %s:%d ",
628 name, eina_log_pid_get(), d->domain_str, file, line);
629}
630
631/* threads, color */
632static void
633eina_log_print_prefix_threads_color_file_func(FILE *fp,
634 const Eina_Log_Domain *d,
635 Eina_Log_Level level,
636 const char *file,
637 const char *fnc,
638 int line)
639{
640 Thread cur;
641
642 DECLARE_LEVEL_NAME_COLOR(level);
643 cur = SELF();
644 if (IS_OTHER(cur))
645 {
646# ifdef _WIN32
647 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
648 color);
649 fprintf(fp, "%s", name);
650 SetConsoleTextAttribute(GetStdHandle(
651 STD_OUTPUT_HANDLE),
652 FOREGROUND_RED | FOREGROUND_GREEN |
653 FOREGROUND_BLUE);
654 fprintf(fp, ":");
655 SetConsoleTextAttribute(GetStdHandle(
656 STD_OUTPUT_HANDLE),
657 eina_log_win32_color_get(d->domain_str));
658 fprintf(fp, "%s[T:", d->name);
659 SetConsoleTextAttribute(GetStdHandle(
660 STD_OUTPUT_HANDLE),
661 FOREGROUND_RED | FOREGROUND_GREEN |
662 FOREGROUND_BLUE);
663 fprintf(fp, "[T:");
664 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
665 FOREGROUND_GREEN | FOREGROUND_BLUE);
666 fprintf(fp, "%lu", (unsigned long)cur);
667 SetConsoleTextAttribute(GetStdHandle(
668 STD_OUTPUT_HANDLE),
669 FOREGROUND_RED | FOREGROUND_GREEN |
670 FOREGROUND_BLUE);
671 fprintf(fp, "] %s:%d ", file, line);
672 SetConsoleTextAttribute(GetStdHandle(
673 STD_OUTPUT_HANDLE),
674 FOREGROUND_INTENSITY | FOREGROUND_RED |
675 FOREGROUND_GREEN | FOREGROUND_BLUE);
676 fprintf(fp, "%s()", fnc);
677 SetConsoleTextAttribute(GetStdHandle(
678 STD_OUTPUT_HANDLE),
679 FOREGROUND_RED | FOREGROUND_GREEN |
680 FOREGROUND_BLUE);
681 fprintf(fp, " ");
682# else
683 fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s[T:"
684 EINA_COLOR_ORANGE "%lu" EINA_COLOR_RESET "] %s:%d "
685 EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ",
686 color, name, eina_log_pid_get() ,d->domain_str,
687 (unsigned long)cur, file, line, fnc);
688# endif
689 return;
690 }
691
692# ifdef _WIN32
693 eina_log_print_prefix_NOthreads_color_file_func(fp,
694 d,
695 level,
696 file,
697 fnc,
698 line);
699# else
700 fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s %s:%d "
701 EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ",
702 color, name, eina_log_pid_get(), d->domain_str, file, line, fnc);
703# endif
704}
705
706static void
707eina_log_print_prefix_threads_color_NOfile_func(FILE *fp,
708 const Eina_Log_Domain *d,
709 Eina_Log_Level level,
710 const char *file __UNUSED__,
711 const char *fnc,
712 int line __UNUSED__)
713{
714 Thread cur;
715
716 DECLARE_LEVEL_NAME_COLOR(level);
717 cur = SELF();
718 if (IS_OTHER(cur))
719 {
720# ifdef _WIN32
721 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
722 color);
723 fprintf(fp, "%s", name);
724 SetConsoleTextAttribute(GetStdHandle(
725 STD_OUTPUT_HANDLE),
726 FOREGROUND_RED | FOREGROUND_GREEN |
727 FOREGROUND_BLUE);
728 fprintf(fp, ":");
729 SetConsoleTextAttribute(GetStdHandle(
730 STD_OUTPUT_HANDLE),
731 eina_log_win32_color_get(d->domain_str));
732 fprintf(fp, "%s[T:", d->name);
733 SetConsoleTextAttribute(GetStdHandle(
734 STD_OUTPUT_HANDLE),
735 FOREGROUND_RED | FOREGROUND_GREEN |
736 FOREGROUND_BLUE);
737 fprintf(fp, "[T:");
738 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
739 FOREGROUND_GREEN | FOREGROUND_BLUE);
740 fprintf(fp, "%lu", (unsigned long)cur);
741 SetConsoleTextAttribute(GetStdHandle(
742 STD_OUTPUT_HANDLE),
743 FOREGROUND_INTENSITY | FOREGROUND_RED |
744 FOREGROUND_GREEN | FOREGROUND_BLUE);
745 fprintf(fp, "%s()", fnc);
746 SetConsoleTextAttribute(GetStdHandle(
747 STD_OUTPUT_HANDLE),
748 FOREGROUND_RED | FOREGROUND_GREEN |
749 FOREGROUND_BLUE);
750 fprintf(fp, " ");
751# else
752 fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s[T:"
753 EINA_COLOR_ORANGE "%lu" EINA_COLOR_RESET "] "
754 EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ",
755 color, name, eina_log_pid_get(), d->domain_str,
756 (unsigned long)cur, fnc);
757# endif
758 return;
759 }
760
761# ifdef _WIN32
762 eina_log_print_prefix_NOthreads_color_NOfile_func(fp,
763 d,
764 level,
765 file,
766 fnc,
767 line);
768# else
769 fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s "
770 EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ",
771 color, name, eina_log_pid_get(), d->domain_str, fnc);
772# endif
773}
774
775static void
776eina_log_print_prefix_threads_color_file_NOfunc(FILE *fp,
777 const Eina_Log_Domain *d,
778 Eina_Log_Level level,
779 const char *file,
780 const char *fnc __UNUSED__,
781 int line)
782{
783 Thread cur;
784
785 DECLARE_LEVEL_NAME_COLOR(level);
786 cur = SELF();
787 if (IS_OTHER(cur))
788 {
789# ifdef _WIN32
790 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
791 color);
792 fprintf(fp, "%s", name);
793 SetConsoleTextAttribute(GetStdHandle(
794 STD_OUTPUT_HANDLE),
795 FOREGROUND_RED | FOREGROUND_GREEN |
796 FOREGROUND_BLUE);
797 fprintf(fp, ":");
798 SetConsoleTextAttribute(GetStdHandle(
799 STD_OUTPUT_HANDLE),
800 eina_log_win32_color_get(d->domain_str));
801 fprintf(fp, "%s[T:", d->name);
802 SetConsoleTextAttribute(GetStdHandle(
803 STD_OUTPUT_HANDLE),
804 FOREGROUND_RED | FOREGROUND_GREEN |
805 FOREGROUND_BLUE);
806 fprintf(fp, "[T:");
807 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
808 FOREGROUND_GREEN | FOREGROUND_BLUE);
809 fprintf(fp, "%lu", (unsigned long)cur);
810 SetConsoleTextAttribute(GetStdHandle(
811 STD_OUTPUT_HANDLE),
812 FOREGROUND_RED | FOREGROUND_GREEN |
813 FOREGROUND_BLUE);
814 fprintf(fp, "] %s:%d ", file, line);
815# else
816 fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s[T:"
817 EINA_COLOR_ORANGE "%lu" EINA_COLOR_RESET "] %s:%d ",
818 color, name, eina_log_pid_get(), d->domain_str,
819 (unsigned long)cur, file, line);
820# endif
821 return;
822 }
823
824# ifdef _WIN32
825 eina_log_print_prefix_NOthreads_color_file_NOfunc(fp,
826 d,
827 level,
828 file,
829 fnc,
830 line);
831# else
832 fprintf(fp, "%s%s" EINA_COLOR_RESET ":%s %s:%d ",
833 color, name, d->domain_str, file, line);
834# endif
835}
836#endif /* EFL_HAVE_THREADS */
837
838static void (*_eina_log_print_prefix)(FILE *fp, const Eina_Log_Domain *d,
839 Eina_Log_Level level, const char *file,
840 const char *fnc,
841 int line) =
842 eina_log_print_prefix_NOthreads_color_file_func;
843
844static inline void
845eina_log_print_prefix_update(void)
846{
847 if (_disable_file && _disable_function)
848 {
849 fprintf(stderr, "ERROR: cannot have " EINA_LOG_ENV_FILE_DISABLE " and "
850 EINA_LOG_ENV_FUNCTION_DISABLE " set at the same time, will "
851 "just disable function.\n");
852 _disable_file = 0;
853 }
854
855#define S(NOthread, NOcolor, NOfile, NOfunc) \
856 _eina_log_print_prefix = \
857 eina_log_print_prefix_ ## NOthread ## threads_ ## NOcolor ## color_ ## \
858 NOfile \
859 ## file_ ## NOfunc ## func
860
861#ifdef EFL_HAVE_THREADS
862 if (_threads_enabled)
863 {
864 if (_disable_color)
865 {
866 if (_disable_file)
867 S(,NO,NO,);
868 else if (_disable_function)
869 S(,NO,,NO);
870 else
871 S(,NO,,);
872 }
873 else
874 {
875 if (_disable_file)
876 S(,,NO,);
877 else if (_disable_function)
878 S(,,,NO);
879 else
880 S(,,,);
881 }
882
883 return;
884 }
885
886#endif
887
888 if (_disable_color)
889 {
890 if (_disable_file)
891 S(NO,NO,NO,);
892 else if (_disable_function)
893 S(NO,NO,,NO);
894 else
895 S(NO,NO,,);
896 }
897 else
898 {
899 if (_disable_file)
900 S(NO,,NO,);
901 else if (_disable_function)
902 S(NO,,,NO);
903 else
904 S(NO,,,);
905 }
906
907#undef S
908}
909
910/*
911 * Creates a colored domain name string.
912 */
913static const char *
914eina_log_domain_str_get(const char *name, const char *color)
915{
916 const char *d;
917
918 if (color)
919 {
920 size_t name_len;
921 size_t color_len;
922
923 name_len = strlen(name);
924 color_len = strlen(color);
925 d =
926 malloc(sizeof(char) *
927 (color_len + name_len + strlen(EINA_COLOR_RESET) + 1));
928 if (!d)
929 return NULL;
930
931 memcpy((char *)d, color, color_len);
932 memcpy((char *)(d + color_len), name, name_len);
933 memcpy((char *)(d + color_len + name_len), EINA_COLOR_RESET,
934 strlen(EINA_COLOR_RESET));
935 ((char *)d)[color_len + name_len + strlen(EINA_COLOR_RESET)] = '\0';
936 }
937 else
938 d = strdup(name);
939
940 return d;
941}
942
943/*
944 * Setups a new logging domain to the name and color specified. Note that this
945 * constructor acts upon an pre-allocated object.
946 */
947static Eina_Log_Domain *
948eina_log_domain_new(Eina_Log_Domain *d, const char *name, const char *color)
949{
950 EINA_SAFETY_ON_NULL_RETURN_VAL(d, NULL);
951 EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
952
953 d->level = EINA_LOG_LEVEL_UNKNOWN;
954 d->deleted = EINA_FALSE;
955
956 if ((color) && (!_disable_color))
957 d->domain_str = eina_log_domain_str_get(name, color);
958 else
959 d->domain_str = eina_log_domain_str_get(name, NULL);
960
961 d->name = strdup(name);
962 d->namelen = strlen(name);
963
964 return d;
965}
966
967/*
968 * Frees internal strings of a log domain, keeping the log domain itself as a
969 * slot for next domain registers.
970 */
971static void
972eina_log_domain_free(Eina_Log_Domain *d)
973{
974 EINA_SAFETY_ON_NULL_RETURN(d);
975
976 if (d->domain_str)
977 free((char *)d->domain_str);
978
979 if (d->name)
980 free((char *)d->name);
981}
982
983/*
984 * Parses domain levels passed through the env var.
985 */
986static void
987eina_log_domain_parse_pendings(void)
988{
989 const char *start;
990
991 if (!(start = getenv(EINA_LOG_ENV_LEVELS)))
992 return;
993
994 // name1:level1,name2:level2,name3:level3,...
995 while (1)
996 {
997 Eina_Log_Domain_Level_Pending *p;
998 char *end = NULL;
999 char *tmp = NULL;
1000 long int level;
1001
1002 end = strchr(start, ':');
1003 if (!end)
1004 break;
1005
1006 // Parse level, keep going if failed
1007 level = strtol((char *)(end + 1), &tmp, 10);
1008 if (tmp == (end + 1))
1009 goto parse_end;
1010
1011 // Parse name
1012 p = malloc(sizeof(Eina_Log_Domain_Level_Pending) + end - start + 1);
1013 if (!p)
1014 break;
1015
1016 p->namelen = end - start;
1017 memcpy((char *)p->name, start, end - start);
1018 ((char *)p->name)[end - start] = '\0';
1019 p->level = level;
1020
1021 _pending_list = eina_inlist_append(_pending_list, EINA_INLIST_GET(p));
1022
1023parse_end:
1024 start = strchr(tmp, ',');
1025 if (start)
1026 start++;
1027 else
1028 break;
1029 }
1030}
1031
1032static void
1033eina_log_domain_parse_pending_globs(void)
1034{
1035 const char *start;
1036
1037 if (!(start = getenv(EINA_LOG_ENV_LEVELS_GLOB)))
1038 return;
1039
1040 // name1:level1,name2:level2,name3:level3,...
1041 while (1)
1042 {
1043 Eina_Log_Domain_Level_Pending *p;
1044 char *end = NULL;
1045 char *tmp = NULL;
1046 long int level;
1047
1048 end = strchr(start, ':');
1049 if (!end)
1050 break;
1051
1052 // Parse level, keep going if failed
1053 level = strtol((char *)(end + 1), &tmp, 10);
1054 if (tmp == (end + 1))
1055 goto parse_end;
1056
1057 // Parse name
1058 p = malloc(sizeof(Eina_Log_Domain_Level_Pending) + end - start + 1);
1059 if (!p)
1060 break;
1061
1062 p->namelen = 0; /* not that useful */
1063 memcpy((char *)p->name, start, end - start);
1064 ((char *)p->name)[end - start] = '\0';
1065 p->level = level;
1066
1067 _glob_list = eina_inlist_append(_glob_list, EINA_INLIST_GET(p));
1068
1069parse_end:
1070 start = strchr(tmp, ',');
1071 if (start)
1072 start++;
1073 else
1074 break;
1075 }
1076}
1077
1078static inline int
1079eina_log_domain_register_unlocked(const char *name, const char *color)
1080{
1081 Eina_Log_Domain_Level_Pending *pending = NULL;
1082 size_t namelen;
1083 unsigned int i;
1084
1085 for (i = 0; i < _log_domains_count; i++)
1086 {
1087 if (_log_domains[i].deleted)
1088 {
1089 // Found a flagged slot, free domain_str and replace slot
1090 eina_log_domain_new(&_log_domains[i], name, color);
1091 goto finish_register;
1092 }
1093 }
1094
1095 if (_log_domains_count >= _log_domains_allocated)
1096 {
1097 Eina_Log_Domain *tmp;
1098 size_t size;
1099
1100 if (!_log_domains)
1101 // special case for init, eina itself will allocate a dozen of domains
1102 size = 24;
1103 else
1104 // grow 8 buckets to minimize reallocs
1105 size = _log_domains_allocated + 8;
1106
1107 tmp = realloc(_log_domains, sizeof(Eina_Log_Domain) * size);
1108
1109 if (tmp)
1110 {
1111 // Success!
1112 _log_domains = tmp;
1113 _log_domains_allocated = size;
1114 }
1115 else
1116 return -1;
1117 }
1118
1119 // Use an allocated slot
1120 eina_log_domain_new(&_log_domains[i], name, color);
1121 _log_domains_count++;
1122
1123finish_register:
1124 namelen = _log_domains[i].namelen;
1125
1126 EINA_INLIST_FOREACH(_pending_list, pending)
1127 {
1128 if ((namelen == pending->namelen) && (strcmp(pending->name, name) == 0))
1129 {
1130 _log_domains[i].level = pending->level;
1131 _pending_list =
1132 eina_inlist_remove(_pending_list, EINA_INLIST_GET(pending));
1133 free(pending);
1134 break;
1135 }
1136 }
1137
1138 if (_log_domains[i].level == EINA_LOG_LEVEL_UNKNOWN)
1139 {
1140 EINA_INLIST_FOREACH(_glob_list, pending)
1141 {
1142 if (!fnmatch(pending->name, name, 0))
1143 {
1144 _log_domains[i].level = pending->level;
1145 break;
1146 }
1147 }
1148 }
1149
1150 // Check if level is still UNKNOWN, set it to global
1151 if (_log_domains[i].level == EINA_LOG_LEVEL_UNKNOWN)
1152 _log_domains[i].level = _log_level;
1153
1154 return i;
1155}
1156
1157static inline Eina_Bool
1158eina_log_term_color_supported(const char *term)
1159{
1160 const char *tail;
1161
1162 if (!term)
1163 return EINA_FALSE;
1164
1165 tail = term + 1;
1166 switch (term[0])
1167 {
1168 /* list of known to support color terminals,
1169 * take from gentoo's portage.
1170 */
1171
1172 case 'x': /* xterm and xterm-color */
1173 return ((strncmp(tail, "term", sizeof("term") - 1) == 0) &&
1174 ((tail[sizeof("term") - 1] == '\0') ||
1175 (strcmp(tail + sizeof("term") - 1, "-color") == 0)));
1176
1177 case 'E': /* Eterm */
1178 case 'a': /* aterm */
1179 case 'k': /* kterm */
1180 return (strcmp(tail, "term") == 0);
1181
1182 case 'r': /* xrvt or rxvt-unicode */
1183 return ((strncmp(tail, "xvt", sizeof("xvt") - 1) == 0) &&
1184 ((tail[sizeof("xvt") - 1] == '\0') ||
1185 (strcmp(tail + sizeof("xvt") - 1, "-unicode") == 0)));
1186
1187 case 's': /* screen */
1188 return (strcmp(tail, "creen") == 0);
1189
1190 case 'g': /* gnome */
1191 return (strcmp(tail, "nome") == 0);
1192
1193 case 'i': /* interix */
1194 return (strcmp(tail, "nterix") == 0);
1195
1196 default:
1197 return EINA_FALSE;
1198 }
1199}
1200
1201static inline void
1202eina_log_domain_unregister_unlocked(int domain)
1203{
1204 Eina_Log_Domain *d;
1205
1206 if ((unsigned int)domain >= _log_domains_count)
1207 return;
1208
1209 d = &_log_domains[domain];
1210 eina_log_domain_free(d);
1211 d->deleted = 1;
1212}
1213
1214static inline void
1215eina_log_print_unlocked(int domain,
1216 Eina_Log_Level level,
1217 const char *file,
1218 const char *fnc,
1219 int line,
1220 const char *fmt,
1221 va_list args)
1222{
1223 Eina_Log_Domain *d;
1224
1225#ifdef EINA_SAFETY_CHECKS
1226 if (EINA_UNLIKELY((unsigned int)domain >= _log_domains_count) ||
1227 EINA_UNLIKELY(domain < 0))
1228 {
1229 if (file && fnc && fmt)
1230 fprintf(
1231 stderr,
1232 "CRI: %s:%d %s() eina_log_print() unknown domain %d, original message format '%s'\n",
1233 file,
1234 line,
1235 fnc,
1236 domain,
1237 fmt);
1238 else
1239 fprintf(
1240 stderr,
1241 "CRI: eina_log_print() unknown domain %d, original message format '%s'\n",
1242 domain,
1243 fmt ? fmt : "");
1244
1245 if (_abort_on_critical)
1246 abort();
1247
1248 return;
1249 }
1250
1251#endif
1252 d = _log_domains + domain;
1253#ifdef EINA_SAFETY_CHECKS
1254 if (EINA_UNLIKELY(d->deleted))
1255 {
1256 fprintf(stderr,
1257 "ERR: eina_log_print() domain %d is deleted\n",
1258 domain);
1259 return;
1260 }
1261
1262#endif
1263
1264 if (level > d->level)
1265 return;
1266
1267#ifdef _WIN32
1268 {
1269 char *wfmt;
1270 char *tmp;
1271
1272 wfmt = strdup(fmt);
1273 if (!wfmt)
1274 {
1275 fprintf(stderr, "ERR: %s: can not allocate memory\n", __FUNCTION__);
1276 return;
1277 }
1278
1279 tmp = wfmt;
1280 while (strchr(tmp, '%'))
1281 {
1282 tmp++;
1283 if (*tmp == 'z')
1284 *tmp = 'I';
1285 }
1286 _print_cb(d, level, file, fnc, line, wfmt, _print_cb_data, args);
1287 free(wfmt);
1288 }
1289#else
1290 _print_cb(d, level, file, fnc, line, fmt, _print_cb_data, args);
1291#endif
1292
1293 if (EINA_UNLIKELY(_abort_on_critical) &&
1294 EINA_UNLIKELY(level <= _abort_level_on_critical))
1295 abort();
1296}
1297
1298#endif
1299
1300/**
1301 * @endcond
1302 */
1303
1304
1305/*============================================================================*
1306* Global *
1307*============================================================================*/
1308
1309/**
1310 * @internal
1311 * @brief Initialize the log module.
1312 *
1313 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
1314 *
1315 * This function sets up the log module of Eina. It is called by
1316 * eina_init().
1317 *
1318 * @see eina_init()
1319 *
1320 * @warning Not-MT: just call this function from main thread! The
1321 * place where this function was called the first time is
1322 * considered the main thread.
1323 */
1324Eina_Bool
1325eina_log_init(void)
1326{
1327#ifdef EINA_ENABLE_LOG
1328 const char *level, *tmp;
1329 int color_disable;
1330
1331 assert((sizeof(_names) / sizeof(_names[0])) == EINA_LOG_LEVELS);
1332
1333 if ((tmp = getenv(EINA_LOG_ENV_COLOR_DISABLE)))
1334 color_disable = atoi(tmp);
1335 else
1336 color_disable = -1;
1337
1338 /* Check if color is explicitly disabled */
1339 if (color_disable == 1)
1340 _disable_color = EINA_TRUE;
1341
1342#ifndef _WIN32
1343 /* color was not explicitly disabled or enabled, guess it */
1344 else if (color_disable == -1)
1345 {
1346 if (!eina_log_term_color_supported(getenv("TERM")))
1347 _disable_color = EINA_TRUE;
1348 else
1349 {
1350 /* if not a terminal, but redirected to a file, disable color */
1351 int fd;
1352
1353 if (_print_cb == eina_log_print_cb_stderr)
1354 fd = STDERR_FILENO;
1355 else if (_print_cb == eina_log_print_cb_stdout)
1356 fd = STDOUT_FILENO;
1357 else
1358 fd = -1;
1359
1360 if ((fd >= 0) && (!isatty(fd)))
1361 _disable_color = EINA_TRUE;
1362 }
1363 }
1364#endif
1365
1366 if ((tmp = getenv(EINA_LOG_ENV_FILE_DISABLE)) && (atoi(tmp) == 1))
1367 _disable_file = EINA_TRUE;
1368
1369 if ((tmp = getenv(EINA_LOG_ENV_FUNCTION_DISABLE)) && (atoi(tmp) == 1))
1370 _disable_function = EINA_TRUE;
1371
1372 if ((tmp = getenv(EINA_LOG_ENV_ABORT)) && (atoi(tmp) == 1))
1373 _abort_on_critical = EINA_TRUE;
1374
1375 if ((tmp = getenv(EINA_LOG_ENV_ABORT_LEVEL)))
1376 _abort_level_on_critical = atoi(tmp);
1377
1378 eina_log_print_prefix_update();
1379
1380 // Global log level
1381 if ((level = getenv(EINA_LOG_ENV_LEVEL)))
1382 _log_level = atoi(level);
1383
1384 // Register UNKNOWN domain, the default logger
1385 EINA_LOG_DOMAIN_GLOBAL = eina_log_domain_register("", NULL);
1386
1387 if (EINA_LOG_DOMAIN_GLOBAL < 0)
1388 {
1389 fprintf(stderr, "Failed to create global logging domain.\n");
1390 return EINA_FALSE;
1391 }
1392
1393 // Parse pending domains passed through EINA_LOG_LEVELS_GLOB
1394 eina_log_domain_parse_pending_globs();
1395
1396 // Parse pending domains passed through EINA_LOG_LEVELS
1397 eina_log_domain_parse_pendings();
1398
1399#endif
1400 return EINA_TRUE;
1401}
1402
1403/**
1404 * @internal
1405 * @brief Shut down the log module.
1406 *
1407 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
1408 *
1409 * This function shuts down the log module set up by
1410 * eina_log_init(). It is called by eina_shutdown().
1411 *
1412 * @see eina_shutdown()
1413 *
1414 * @warning Not-MT: just call this function from main thread! The
1415 * place where eina_log_init() (eina_init()) was called the
1416 * first time is considered the main thread.
1417 */
1418Eina_Bool
1419eina_log_shutdown(void)
1420{
1421#ifdef EINA_ENABLE_LOG
1422 Eina_Inlist *tmp;
1423
1424 while (_log_domains_count--)
1425 {
1426 if (_log_domains[_log_domains_count].deleted)
1427 continue;
1428
1429 eina_log_domain_free(&_log_domains[_log_domains_count]);
1430 }
1431
1432 free(_log_domains);
1433
1434 _log_domains = NULL;
1435 _log_domains_count = 0;
1436 _log_domains_allocated = 0;
1437
1438 while (_glob_list)
1439 {
1440 tmp = _glob_list;
1441 _glob_list = _glob_list->next;
1442 free(tmp);
1443 }
1444
1445 while (_pending_list)
1446 {
1447 tmp = _pending_list;
1448 _pending_list = _pending_list->next;
1449 free(tmp);
1450 }
1451
1452#endif
1453 return EINA_TRUE;
1454}
1455
1456#ifdef EFL_HAVE_THREADS
1457
1458/**
1459 * @internal
1460 * @brief Activate the log mutex.
1461 *
1462 * This function activate the mutex in the eina log module. It is called by
1463 * eina_threads_init().
1464 *
1465 * @see eina_threads_init()
1466 */
1467void
1468eina_log_threads_init(void)
1469{
1470#ifdef EINA_ENABLE_LOG
1471 if (_threads_inited) return;
1472 _main_thread = SELF();
1473 if (!INIT()) return;
1474 _threads_inited = EINA_TRUE;
1475#endif
1476}
1477
1478/**
1479 * @internal
1480 * @brief Shut down the log mutex.
1481 *
1482 * This function shuts down the mutex in the log module.
1483 * It is called by eina_threads_shutdown().
1484 *
1485 * @see eina_threads_shutdown()
1486 */
1487void
1488eina_log_threads_shutdown(void)
1489{
1490#ifdef EINA_ENABLE_LOG
1491 if (!_threads_inited) return;
1492 CHECK_MAIN();
1493 SHUTDOWN();
1494 _threads_enabled = EINA_FALSE;
1495 _threads_inited = EINA_FALSE;
1496#endif
1497}
1498
1499#endif
1500
1501/*============================================================================*
1502* API *
1503*============================================================================*/
1504
1505/**
1506 * @cond LOCAL
1507 */
1508
1509EAPI int EINA_LOG_DOMAIN_GLOBAL = 0;
1510
1511/**
1512 * @endcond
1513 */
1514
1515EAPI void
1516eina_log_threads_enable(void)
1517{
1518#if defined (EFL_HAVE_THREADS) && defined (EINA_ENABLE_LOG)
1519 if (_threads_enabled) return;
1520 if (!_threads_inited) eina_log_threads_init();
1521 _threads_enabled = EINA_TRUE;
1522 eina_log_print_prefix_update();
1523#endif
1524}
1525
1526EAPI void
1527eina_log_print_cb_set(Eina_Log_Print_Cb cb, void *data)
1528{
1529#ifdef EINA_ENABLE_LOG
1530 LOG_LOCK();
1531 _print_cb = cb;
1532 _print_cb_data = data;
1533 eina_log_print_prefix_update();
1534 LOG_UNLOCK();
1535#else
1536 (void) cb;
1537 (void) data;
1538#endif
1539}
1540
1541EAPI void
1542eina_log_level_set(int level)
1543{
1544#ifdef EINA_ENABLE_LOG
1545 _log_level = level;
1546 if (EINA_LIKELY((EINA_LOG_DOMAIN_GLOBAL >= 0) &&
1547 ((unsigned int)EINA_LOG_DOMAIN_GLOBAL < _log_domains_count)))
1548 _log_domains[EINA_LOG_DOMAIN_GLOBAL].level = level;
1549#else
1550 (void) level;
1551#endif
1552}
1553
1554EAPI int
1555eina_log_level_get(void)
1556{
1557#ifdef EINA_ENABLE_LOG
1558 return _log_level;
1559#else
1560 return 0;
1561#endif
1562}
1563
1564EAPI Eina_Bool
1565eina_log_main_thread_check(void)
1566{
1567#if defined (EFL_HAVE_THREADS) && defined (EINA_ENABLE_LOG)
1568 return ((!_threads_enabled) || IS_MAIN(SELF()));
1569#else
1570 return EINA_TRUE;
1571#endif
1572}
1573
1574EAPI void
1575eina_log_color_disable_set(Eina_Bool disabled)
1576{
1577#ifdef EINA_ENABLE_LOG
1578 _disable_color = disabled;
1579#else
1580 (void) disabled;
1581#endif
1582}
1583
1584EAPI Eina_Bool
1585eina_log_color_disable_get(void)
1586{
1587#ifdef EINA_ENABLE_LOG
1588 return _disable_color;
1589#else
1590 return EINA_TRUE;
1591#endif
1592}
1593
1594EAPI void
1595eina_log_file_disable_set(Eina_Bool disabled)
1596{
1597#ifdef EINA_ENABLE_LOG
1598 _disable_file = disabled;
1599#else
1600 (void) disabled;
1601#endif
1602}
1603
1604EAPI Eina_Bool
1605eina_log_file_disable_get(void)
1606{
1607#ifdef EINA_ENABLE_LOG
1608 return _disable_file;
1609#else
1610 return EINA_TRUE;
1611#endif
1612}
1613
1614EAPI void
1615eina_log_function_disable_set(Eina_Bool disabled)
1616{
1617#ifdef EINA_ENABLE_LOG
1618 _disable_function = disabled;
1619#else
1620 (void) disabled;
1621#endif
1622}
1623
1624EAPI Eina_Bool
1625eina_log_function_disable_get(void)
1626{
1627#ifdef EINA_ENABLE_LOG
1628 return _disable_function;
1629#else
1630 return EINA_TRUE;
1631#endif
1632}
1633
1634EAPI void
1635eina_log_abort_on_critical_set(Eina_Bool abort_on_critical)
1636{
1637#ifdef EINA_ENABLE_LOG
1638 _abort_on_critical = abort_on_critical;
1639#else
1640 (void) abort_on_critical;
1641#endif
1642}
1643
1644EAPI Eina_Bool
1645eina_log_abort_on_critical_get(void)
1646{
1647#ifdef EINA_ENABLE_LOG
1648 return _abort_on_critical;
1649#else
1650 return EINA_FALSE;
1651#endif
1652}
1653
1654EAPI void
1655eina_log_abort_on_critical_level_set(int critical_level)
1656{
1657#ifdef EINA_ENABLE_LOG
1658 _abort_level_on_critical = critical_level;
1659#else
1660 (void) critical_level;
1661#endif
1662}
1663
1664EAPI int
1665eina_log_abort_on_critical_level_get(void)
1666{
1667#ifdef EINA_ENABLE_LOG
1668 return _abort_level_on_critical;
1669#else
1670 return 0;
1671#endif
1672}
1673
1674EAPI int
1675eina_log_domain_register(const char *name, const char *color)
1676{
1677#ifdef EINA_ENABLE_LOG
1678 int r;
1679
1680 EINA_SAFETY_ON_NULL_RETURN_VAL(name, -1);
1681
1682 LOG_LOCK();
1683 r = eina_log_domain_register_unlocked(name, color);
1684 LOG_UNLOCK();
1685 return r;
1686#else
1687 (void) name;
1688 (void) color;
1689 return 0;
1690#endif
1691}
1692
1693EAPI void
1694eina_log_domain_unregister(int domain)
1695{
1696#ifdef EINA_ENABLE_LOG
1697 EINA_SAFETY_ON_FALSE_RETURN(domain >= 0);
1698 LOG_LOCK();
1699 eina_log_domain_unregister_unlocked(domain);
1700 LOG_UNLOCK();
1701#else
1702 (void) domain;
1703#endif
1704}
1705
1706EAPI void
1707eina_log_domain_level_set(const char *domain_name, int level)
1708{
1709#ifdef EINA_ENABLE_LOG
1710 Eina_Log_Domain_Level_Pending *pending;
1711 size_t namelen;
1712 unsigned int i;
1713
1714 EINA_SAFETY_ON_NULL_RETURN(domain_name);
1715
1716 namelen = strlen(domain_name);
1717
1718 for (i = 0; i < _log_domains_count; i++)
1719 {
1720 if (_log_domains[i].deleted)
1721 continue;
1722
1723 if ((namelen != _log_domains[i].namelen) ||
1724 (strcmp(_log_domains[i].name, domain_name) != 0))
1725 continue;
1726
1727 _log_domains[i].level = level;
1728 return;
1729 }
1730
1731 EINA_INLIST_FOREACH(_pending_list, pending)
1732 {
1733 if ((namelen == pending->namelen) &&
1734 (strcmp(pending->name, domain_name) == 0))
1735 {
1736 pending->level = level;
1737 return;
1738 }
1739 }
1740
1741 pending = malloc(sizeof(Eina_Log_Domain_Level_Pending) + namelen + 1);
1742 if (!pending)
1743 return;
1744
1745 pending->level = level;
1746 pending->namelen = namelen;
1747 memcpy(pending->name, domain_name, namelen + 1);
1748
1749 _pending_list = eina_inlist_append(_pending_list, EINA_INLIST_GET(pending));
1750#else
1751 (void) domain_name;
1752 (void) level;
1753#endif
1754}
1755
1756EAPI int
1757eina_log_domain_level_get(const char *domain_name)
1758{
1759#ifdef EINA_ENABLE_LOG
1760 Eina_Log_Domain_Level_Pending *pending;
1761 size_t namelen;
1762 unsigned int i;
1763
1764 EINA_SAFETY_ON_NULL_RETURN_VAL(domain_name, EINA_LOG_LEVEL_UNKNOWN);
1765
1766 namelen = strlen(domain_name);
1767
1768 for (i = 0; i < _log_domains_count; i++)
1769 {
1770 if (_log_domains[i].deleted)
1771 continue;
1772
1773 if ((namelen != _log_domains[i].namelen) ||
1774 (strcmp(_log_domains[i].name, domain_name) != 0))
1775 continue;
1776
1777 return _log_domains[i].level;
1778 }
1779
1780 EINA_INLIST_FOREACH(_pending_list, pending)
1781 {
1782 if ((namelen == pending->namelen) &&
1783 (strcmp(pending->name, domain_name) == 0))
1784 return pending->level;
1785 }
1786
1787 EINA_INLIST_FOREACH(_glob_list, pending)
1788 {
1789 if (!fnmatch(pending->name, domain_name, 0))
1790 return pending->level;
1791 }
1792
1793 return _log_level;
1794#else
1795 (void) domain_name;
1796 return 0;
1797#endif
1798}
1799
1800EAPI int
1801eina_log_domain_registered_level_get(int domain)
1802{
1803#ifdef EINA_ENABLE_LOG
1804 EINA_SAFETY_ON_FALSE_RETURN_VAL(domain >= 0, EINA_LOG_LEVEL_UNKNOWN);
1805 EINA_SAFETY_ON_FALSE_RETURN_VAL((unsigned int)domain < _log_domains_count,
1806 EINA_LOG_LEVEL_UNKNOWN);
1807 EINA_SAFETY_ON_TRUE_RETURN_VAL(_log_domains[domain].deleted,
1808 EINA_LOG_LEVEL_UNKNOWN);
1809 return _log_domains[domain].level;
1810#else
1811 (void) domain;
1812 return 0;
1813#endif
1814}
1815
1816EAPI void
1817eina_log_print_cb_stderr(const Eina_Log_Domain *d,
1818 Eina_Log_Level level,
1819 const char *file,
1820 const char *fnc,
1821 int line,
1822 const char *fmt,
1823 __UNUSED__ void *data,
1824 va_list args)
1825{
1826#ifdef EINA_ENABLE_LOG
1827 _eina_log_print_prefix(stderr, d, level, file, fnc, line);
1828 vfprintf(stderr, fmt, args);
1829 putc('\n', stderr);
1830#else
1831 (void) d;
1832 (void) level;
1833 (void) file;
1834 (void) fnc;
1835 (void) line;
1836 (void) fmt;
1837 (void) data;
1838 (void) args;
1839#endif
1840}
1841
1842EAPI void
1843eina_log_print_cb_stdout(const Eina_Log_Domain *d,
1844 Eina_Log_Level level,
1845 const char *file,
1846 const char *fnc,
1847 int line,
1848 const char *fmt,
1849 __UNUSED__ void *data,
1850 va_list args)
1851{
1852#ifdef EINA_ENABLE_LOG
1853 _eina_log_print_prefix(stdout, d, level, file, fnc, line);
1854 vprintf(fmt, args);
1855 putchar('\n');
1856#else
1857 (void) d;
1858 (void) level;
1859 (void) file;
1860 (void) fnc;
1861 (void) line;
1862 (void) fmt;
1863 (void) data;
1864 (void) args;
1865#endif
1866}
1867
1868EAPI void
1869eina_log_print_cb_file(const Eina_Log_Domain *d,
1870 __UNUSED__ Eina_Log_Level level,
1871 const char *file,
1872 const char *fnc,
1873 int line,
1874 const char *fmt,
1875 void *data,
1876 va_list args)
1877{
1878#ifdef EINA_ENABLE_LOG
1879 FILE *f = data;
1880#ifdef EFL_HAVE_THREADS
1881 if (_threads_enabled)
1882 {
1883 Thread cur;
1884
1885 cur = SELF();
1886 if (IS_OTHER(cur))
1887 {
1888 fprintf(f, "%s[T:%lu] %s:%d %s() ", d->name, (unsigned long)cur,
1889 file, line, fnc);
1890 goto end;
1891 }
1892 }
1893
1894#endif
1895 fprintf(f, "%s<%u> %s:%d %s() ", d->name, eina_log_pid_get(),
1896 file, line, fnc);
1897#ifdef EFL_HAVE_THREADS
1898end:
1899#endif
1900 vfprintf(f, fmt, args);
1901 putc('\n', f);
1902#else
1903 (void) d;
1904 (void) file;
1905 (void) fnc;
1906 (void) line;
1907 (void) fmt;
1908 (void) data;
1909 (void) args;
1910#endif
1911}
1912
1913EAPI void
1914eina_log_print(int domain, Eina_Log_Level level, const char *file,
1915 const char *fnc, int line, const char *fmt, ...)
1916{
1917#ifdef EINA_ENABLE_LOG
1918 va_list args;
1919
1920#ifdef EINA_SAFETY_CHECKS
1921 if (EINA_UNLIKELY(!file))
1922 {
1923 fputs("ERR: eina_log_print() file == NULL\n", stderr);
1924 return;
1925 }
1926
1927 if (EINA_UNLIKELY(!fnc))
1928 {
1929 fputs("ERR: eina_log_print() fnc == NULL\n", stderr);
1930 return;
1931 }
1932
1933 if (EINA_UNLIKELY(!fmt))
1934 {
1935 fputs("ERR: eina_log_print() fmt == NULL\n", stderr);
1936 return;
1937 }
1938
1939#endif
1940 va_start(args, fmt);
1941 LOG_LOCK();
1942 eina_log_print_unlocked(domain, level, file, fnc, line, fmt, args);
1943 LOG_UNLOCK();
1944 va_end(args);
1945#else
1946 (void) domain;
1947 (void) level;
1948 (void) file;
1949 (void) fnc;
1950 (void) line;
1951 (void) fmt;
1952#endif
1953}
1954
1955EAPI void
1956eina_log_vprint(int domain, Eina_Log_Level level, const char *file,
1957 const char *fnc, int line, const char *fmt, va_list args)
1958{
1959#ifdef EINA_ENABLE_LOG
1960
1961#ifdef EINA_SAFETY_CHECKS
1962 if (EINA_UNLIKELY(!file))
1963 {
1964 fputs("ERR: eina_log_print() file == NULL\n", stderr);
1965 return;
1966 }
1967
1968 if (EINA_UNLIKELY(!fnc))
1969 {
1970 fputs("ERR: eina_log_print() fnc == NULL\n", stderr);
1971 return;
1972 }
1973
1974 if (EINA_UNLIKELY(!fmt))
1975 {
1976 fputs("ERR: eina_log_print() fmt == NULL\n", stderr);
1977 return;
1978 }
1979
1980#endif
1981 LOG_LOCK();
1982 eina_log_print_unlocked(domain, level, file, fnc, line, fmt, args);
1983 LOG_UNLOCK();
1984#else
1985 (void) domain;
1986 (void) level;
1987 (void) file;
1988 (void) fnc;
1989 (void) line;
1990 (void) fmt;
1991 (void) args;
1992#endif
1993}