1 /* EINA - EFL data type library
2 * Copyright (C) 2007-2009 Jorge Luis Zapata Muga, Cedric Bail, Andre Dieb
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.
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.
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/>.
32 #if defined HAVE_EXECINFO_H && defined HAVE_BACKTRACE && defined HAVE_BACKTRACE_SYMBOLS
33 # include <execinfo.h>
34 # define EINA_LOG_BACKTRACE
42 #ifdef EFL_HAVE_POSIX_THREADS
50 #include "eina_config.h"
51 #include "eina_private.h"
52 #include "eina_inlist.h"
54 /* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
55 #include "eina_safety_checks.h"
59 * + printing logs to stdout or stderr can be implemented
60 * using a queue, useful for multiple threads printing
61 * + add a wrapper for assert?
64 /*============================================================================*
66 *============================================================================*/
72 #define EINA_LOG_ENV_ABORT "EINA_LOG_ABORT"
73 #define EINA_LOG_ENV_ABORT_LEVEL "EINA_LOG_ABORT_LEVEL"
74 #define EINA_LOG_ENV_LEVEL "EINA_LOG_LEVEL"
75 #define EINA_LOG_ENV_LEVELS "EINA_LOG_LEVELS"
76 #define EINA_LOG_ENV_LEVELS_GLOB "EINA_LOG_LEVELS_GLOB"
77 #define EINA_LOG_ENV_COLOR_DISABLE "EINA_LOG_COLOR_DISABLE"
78 #define EINA_LOG_ENV_FILE_DISABLE "EINA_LOG_FILE_DISABLE"
79 #define EINA_LOG_ENV_FUNCTION_DISABLE "EINA_LOG_FUNCTION_DISABLE"
80 #define EINA_LOG_ENV_BACKTRACE "EINA_LOG_BACKTRACE"
82 #ifdef EINA_ENABLE_LOG
84 // Structure for storing domain level settings passed from the command line
85 // that will be matched with application-defined domains.
86 typedef struct _Eina_Log_Domain_Level_Pending Eina_Log_Domain_Level_Pending;
87 struct _Eina_Log_Domain_Level_Pending
96 * List of levels for domains set by the user before the domains are registered,
97 * updates the domain levels on the first log and clears itself.
99 static Eina_Inlist *_pending_list = NULL;
100 static Eina_Inlist *_glob_list = NULL;
102 // Disable color flag (can be changed through the env var
103 // EINA_LOG_ENV_COLOR_DISABLE).
104 static Eina_Bool _disable_color = EINA_FALSE;
105 static Eina_Bool _disable_file = EINA_FALSE;
106 static Eina_Bool _disable_function = EINA_FALSE;
107 static Eina_Bool _abort_on_critical = EINA_FALSE;
108 static int _abort_level_on_critical = EINA_LOG_LEVEL_CRITICAL;
110 #ifdef EINA_LOG_BACKTRACE
111 static int _backtrace_level = -1;
114 #ifdef EFL_HAVE_THREADS
116 static Eina_Bool _threads_enabled = EINA_FALSE;
117 static Eina_Bool _threads_inited = EINA_FALSE;
119 # ifdef EFL_HAVE_POSIX_THREADS
121 typedef pthread_t Thread;
123 static pthread_t _main_thread;
125 # define SELF() pthread_self()
126 # define IS_MAIN(t) pthread_equal(t, _main_thread)
127 # define IS_OTHER(t) EINA_UNLIKELY(!IS_MAIN(t))
128 # define CHECK_MAIN(...) \
130 if (!IS_MAIN(pthread_self())) { \
132 "ERR: not main thread! current=%lu, main=%lu\n", \
133 (unsigned long)pthread_self(), \
134 (unsigned long)_main_thread); \
135 return __VA_ARGS__; \
139 # ifdef EFL_HAVE_POSIX_THREADS_SPINLOCK
141 static pthread_spinlock_t _log_lock;
143 static Eina_Bool _eina_log_spinlock_init(void)
145 if (pthread_spin_init(&_log_lock, PTHREAD_PROCESS_PRIVATE) == 0)
149 "ERROR: pthread_spin_init(%p, PTHREAD_PROCESS_PRIVATE): %s\n",
150 &_log_lock, strerror(errno));
154 # define LOG_LOCK() \
155 if (_threads_enabled) \
158 fprintf(stderr, "+++LOG LOG_LOCKED! [%s, %lu]\n", \
159 __FUNCTION__, (unsigned long)pthread_self()); } \
160 if (EINA_UNLIKELY(_threads_enabled)) { \
161 pthread_spin_lock(&_log_lock); } \
163 # define LOG_UNLOCK() \
164 if (_threads_enabled) \
166 if (EINA_UNLIKELY(_threads_enabled)) { \
167 pthread_spin_unlock(&_log_lock); } \
170 "---LOG LOG_UNLOCKED! [%s, %lu]\n", \
171 __FUNCTION__, (unsigned long)pthread_self()); } \
173 # define INIT() _eina_log_spinlock_init()
174 # define SHUTDOWN() pthread_spin_destroy(&_log_lock)
176 # else /* ! EFL_HAVE_POSIX_THREADS_SPINLOCK */
178 static pthread_mutex_t _log_mutex = PTHREAD_MUTEX_INITIALIZER;
179 # define LOG_LOCK() if(_threads_enabled) {pthread_mutex_lock(&_log_mutex); }
180 # define LOG_UNLOCK() if(_threads_enabled) {pthread_mutex_unlock(&_log_mutex); }
182 # define SHUTDOWN() do {} while (0)
184 # endif /* ! EFL_HAVE_POSIX_THREADS_SPINLOCK */
186 # else /* EFL_HAVE_WIN32_THREADS */
188 typedef DWORD Thread;
190 static DWORD _main_thread;
192 # define SELF() GetCurrentThreadId()
193 # define IS_MAIN(t) (t == _main_thread)
194 # define IS_OTHER(t) EINA_UNLIKELY(!IS_MAIN(t))
195 # define CHECK_MAIN(...) \
197 if (!IS_MAIN(GetCurrentThreadId())) { \
199 "ERR: not main thread! current=%lu, main=%lu\n", \
200 GetCurrentThreadId(), _main_thread); \
201 return __VA_ARGS__; \
205 static HANDLE _log_mutex = NULL;
207 # define LOG_LOCK() if(_threads_enabled) WaitForSingleObject(_log_mutex, INFINITE)
208 # define LOG_UNLOCK() if(_threads_enabled) ReleaseMutex(_log_mutex)
209 # define INIT() ((_log_mutex = CreateMutex(NULL, FALSE, NULL)) ? 1 : 0)
210 # define SHUTDOWN() if (_log_mutex) CloseHandle(_log_mutex)
212 # endif /* EFL_HAVE_WIN32_THREADS */
214 #else /* ! EFL_HAVE_THREADS */
216 # define LOG_LOCK() do {} while (0)
217 # define LOG_UNLOCK() do {} while (0)
218 # define IS_MAIN(t) (1)
219 # define IS_OTHER(t) (0)
220 # define CHECK_MAIN(...) do {} while (0)
222 # define SHUTDOWN() do {} while (0)
224 #endif /* ! EFL_HAVE_THREADS */
227 // List of domains registered
228 static Eina_Log_Domain *_log_domains = NULL;
229 static unsigned int _log_domains_count = 0;
230 static size_t _log_domains_allocated = 0;
232 // Default function for printing on domains
233 static Eina_Log_Print_Cb _print_cb = eina_log_print_cb_stderr;
234 static void *_print_cb_data = NULL;
237 static Eina_Log_Level _log_level = EINA_LOG_LEVEL_DBG;
239 static Eina_Log_Level _log_level = EINA_LOG_LEVEL_CRITICAL;
241 static Eina_Log_Level _log_level = EINA_LOG_LEVEL_ERR;
244 /* NOTE: if you change this, also change:
245 * eina_log_print_level_name_get()
246 * eina_log_print_level_name_color_get()
248 static const char *_names[] = {
258 eina_log_win32_color_get(const char *domain_str)
267 str = strdup(domain_str);
271 /* this should not append */
272 if (str[0] != '\033')
278 /* we skip the first char and the [ */
279 tmp = tmp2 = str + 2;
296 lighted = atol(tmp2);
310 ret = FOREGROUND_INTENSITY;
313 ret |= FOREGROUND_RED;
315 ret |= FOREGROUND_GREEN;
317 ret |= FOREGROUND_RED | FOREGROUND_GREEN;
319 ret |= FOREGROUND_BLUE;
321 ret |= FOREGROUND_GREEN | FOREGROUND_BLUE;
323 ret |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
329 static inline unsigned int
330 eina_log_pid_get(void)
332 return (unsigned int)getpid();
336 eina_log_print_level_name_get(int level, const char **p_name)
339 /* NOTE: if you change this, also change
340 * eina_log_print_level_name_color_get()
341 * eina_log_level_name_get() (at eina_inline_log.x)
343 if (EINA_UNLIKELY(level < 0))
345 snprintf(buf, sizeof(buf), "%03d", level);
348 else if (EINA_UNLIKELY(level >= EINA_LOG_LEVELS))
350 snprintf(buf, sizeof(buf), "%03d", level);
354 *p_name = _names[level];
359 eina_log_print_level_name_color_get(int level,
364 /* NOTE: if you change this, also change:
365 * eina_log_print_level_name_get()
367 if (EINA_UNLIKELY(level < 0))
369 snprintf(buf, sizeof(buf), "%03d", level);
372 else if (EINA_UNLIKELY(level >= EINA_LOG_LEVELS))
374 snprintf(buf, sizeof(buf), "%03d", level);
378 *p_name = _names[level];
380 *p_color = eina_log_win32_color_get(eina_log_level_color_get(level));
384 eina_log_print_level_name_color_get(int level,
386 const char **p_color)
389 /* NOTE: if you change this, also change:
390 * eina_log_print_level_name_get()
392 if (EINA_UNLIKELY(level < 0))
394 snprintf(buf, sizeof(buf), "%03d", level);
397 else if (EINA_UNLIKELY(level >= EINA_LOG_LEVELS))
399 snprintf(buf, sizeof(buf), "%03d", level);
403 *p_name = _names[level];
405 *p_color = eina_log_level_color_get(level);
409 #define DECLARE_LEVEL_NAME(level) const char *name; \
410 eina_log_print_level_name_get(level, &name)
412 # define DECLARE_LEVEL_NAME_COLOR(level) const char *name; int color; \
413 eina_log_print_level_name_color_get(level, &name, &color)
415 # define DECLARE_LEVEL_NAME_COLOR(level) const char *name, *color; \
416 eina_log_print_level_name_color_get(level, &name, &color)
419 /** No threads, No color */
421 eina_log_print_prefix_NOthreads_NOcolor_file_func(FILE *fp,
422 const Eina_Log_Domain *d,
423 Eina_Log_Level level,
428 DECLARE_LEVEL_NAME(level);
429 fprintf(fp, "%s<%u>:%s %s:%d %s() ", name, eina_log_pid_get(),
430 d->domain_str, file, line, fnc);
434 eina_log_print_prefix_NOthreads_NOcolor_NOfile_func(FILE *fp,
435 const Eina_Log_Domain *d,
436 Eina_Log_Level level,
437 const char *file __UNUSED__,
441 DECLARE_LEVEL_NAME(level);
442 fprintf(fp, "%s<%u>:%s %s() ", name, eina_log_pid_get(), d->domain_str,
447 eina_log_print_prefix_NOthreads_NOcolor_file_NOfunc(FILE *fp,
448 const Eina_Log_Domain *d,
449 Eina_Log_Level level,
451 const char *fnc __UNUSED__,
454 DECLARE_LEVEL_NAME(level);
455 fprintf(fp, "%s<%u>:%s %s:%d ", name, eina_log_pid_get(), d->domain_str,
459 /* No threads, color */
461 eina_log_print_prefix_NOthreads_color_file_func(FILE *fp,
462 const Eina_Log_Domain *d,
463 Eina_Log_Level level,
468 DECLARE_LEVEL_NAME_COLOR(level);
470 fprintf(fp, "%s<%u>:%s %s:%d %s() ", name, eina_log_pid_get(),
471 d->domain_str, file, line, fnc);
473 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
475 fprintf(fp, "%s", name);
476 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
477 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
479 SetConsoleTextAttribute(GetStdHandle(
481 eina_log_win32_color_get(d->domain_str));
482 fprintf(fp, "%s", d->name);
483 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
484 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
485 fprintf(fp, " %s:%d ", file, line);
486 SetConsoleTextAttribute(GetStdHandle(
488 FOREGROUND_INTENSITY | FOREGROUND_RED |
489 FOREGROUND_GREEN | FOREGROUND_BLUE);
490 fprintf(fp, "%s()", fnc);
491 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
492 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
495 fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s %s:%d "
496 EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ",
497 color, name, eina_log_pid_get(), d->domain_str, file, line, fnc);
502 eina_log_print_prefix_NOthreads_color_NOfile_func(FILE *fp,
503 const Eina_Log_Domain *d,
504 Eina_Log_Level level,
505 const char *file __UNUSED__,
509 DECLARE_LEVEL_NAME_COLOR(level);
511 fprintf(fp, "%s<%u>:%s %s() ", name, eina_log_pid_get(), d->domain_str,
514 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
516 fprintf(fp, "%s", name);
517 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
518 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
520 SetConsoleTextAttribute(GetStdHandle(
522 eina_log_win32_color_get(d->domain_str));
523 fprintf(fp, "%s", d->name);
524 SetConsoleTextAttribute(GetStdHandle(
526 FOREGROUND_INTENSITY | FOREGROUND_RED |
527 FOREGROUND_GREEN | FOREGROUND_BLUE);
528 fprintf(fp, "%s()", fnc);
529 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
530 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
533 fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s "
534 EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ",
535 color, name, eina_log_pid_get(), d->domain_str, fnc);
540 eina_log_print_prefix_NOthreads_color_file_NOfunc(FILE *fp,
541 const Eina_Log_Domain *d,
542 Eina_Log_Level level,
544 const char *fnc __UNUSED__,
547 DECLARE_LEVEL_NAME_COLOR(level);
549 fprintf(fp, "%s<%u>:%s %s:%d ", name, eina_log_pid_get(), d->domain_str,
552 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
554 fprintf(fp, "%s", name);
555 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
556 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
558 SetConsoleTextAttribute(GetStdHandle(
560 eina_log_win32_color_get(d->domain_str));
561 fprintf(fp, "%s", d->name);
562 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
563 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
564 fprintf(fp, " %s:%d ", file, line);
566 fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s %s:%d ",
567 color, name, eina_log_pid_get(), d->domain_str, file, line);
571 /** threads, No color */
572 #ifdef EFL_HAVE_THREADS
574 eina_log_print_prefix_threads_NOcolor_file_func(FILE *fp,
575 const Eina_Log_Domain *d,
576 Eina_Log_Level level,
583 DECLARE_LEVEL_NAME(level);
587 fprintf(fp, "%s<%u>:%s[T:%lu] %s:%d %s() ",
588 name, eina_log_pid_get(), d->domain_str,
589 (unsigned long)cur, file, line, fnc);
592 fprintf(fp, "%s<%u>:%s %s:%d %s() ",
593 name, eina_log_pid_get(), d->domain_str, file, line, fnc);
597 eina_log_print_prefix_threads_NOcolor_NOfile_func(FILE *fp,
598 const Eina_Log_Domain *d,
599 Eina_Log_Level level,
600 const char *file __UNUSED__,
606 DECLARE_LEVEL_NAME(level);
610 fprintf(fp, "%s<%u>:%s[T:%lu] %s() ",
611 name, eina_log_pid_get(), d->domain_str,
612 (unsigned long)cur, fnc);
615 fprintf(fp, "%s<%u>:%s %s() ",
616 name, eina_log_pid_get(), d->domain_str, fnc);
620 eina_log_print_prefix_threads_NOcolor_file_NOfunc(FILE *fp,
621 const Eina_Log_Domain *d,
622 Eina_Log_Level level,
624 const char *fnc __UNUSED__,
629 DECLARE_LEVEL_NAME(level);
633 fprintf(fp, "%s<%u>:%s[T:%lu] %s:%d ",
634 name, eina_log_pid_get(), d->domain_str, (unsigned long)cur,
639 fprintf(fp, "%s<%u>:%s %s:%d ",
640 name, eina_log_pid_get(), d->domain_str, file, line);
645 eina_log_print_prefix_threads_color_file_func(FILE *fp,
646 const Eina_Log_Domain *d,
647 Eina_Log_Level level,
654 DECLARE_LEVEL_NAME_COLOR(level);
659 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
661 fprintf(fp, "%s", name);
662 SetConsoleTextAttribute(GetStdHandle(
664 FOREGROUND_RED | FOREGROUND_GREEN |
667 SetConsoleTextAttribute(GetStdHandle(
669 eina_log_win32_color_get(d->domain_str));
670 fprintf(fp, "%s[T:", d->name);
671 SetConsoleTextAttribute(GetStdHandle(
673 FOREGROUND_RED | FOREGROUND_GREEN |
676 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
677 FOREGROUND_GREEN | FOREGROUND_BLUE);
678 fprintf(fp, "%lu", (unsigned long)cur);
679 SetConsoleTextAttribute(GetStdHandle(
681 FOREGROUND_RED | FOREGROUND_GREEN |
683 fprintf(fp, "] %s:%d ", file, line);
684 SetConsoleTextAttribute(GetStdHandle(
686 FOREGROUND_INTENSITY | FOREGROUND_RED |
687 FOREGROUND_GREEN | FOREGROUND_BLUE);
688 fprintf(fp, "%s()", fnc);
689 SetConsoleTextAttribute(GetStdHandle(
691 FOREGROUND_RED | FOREGROUND_GREEN |
695 fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s[T:"
696 EINA_COLOR_ORANGE "%lu" EINA_COLOR_RESET "] %s:%d "
697 EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ",
698 color, name, eina_log_pid_get() ,d->domain_str,
699 (unsigned long)cur, file, line, fnc);
705 eina_log_print_prefix_NOthreads_color_file_func(fp,
712 fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s %s:%d "
713 EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ",
714 color, name, eina_log_pid_get(), d->domain_str, file, line, fnc);
719 eina_log_print_prefix_threads_color_NOfile_func(FILE *fp,
720 const Eina_Log_Domain *d,
721 Eina_Log_Level level,
722 const char *file __UNUSED__,
728 DECLARE_LEVEL_NAME_COLOR(level);
733 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
735 fprintf(fp, "%s", name);
736 SetConsoleTextAttribute(GetStdHandle(
738 FOREGROUND_RED | FOREGROUND_GREEN |
741 SetConsoleTextAttribute(GetStdHandle(
743 eina_log_win32_color_get(d->domain_str));
744 fprintf(fp, "%s[T:", d->name);
745 SetConsoleTextAttribute(GetStdHandle(
747 FOREGROUND_RED | FOREGROUND_GREEN |
750 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
751 FOREGROUND_GREEN | FOREGROUND_BLUE);
752 fprintf(fp, "%lu", (unsigned long)cur);
753 SetConsoleTextAttribute(GetStdHandle(
755 FOREGROUND_INTENSITY | FOREGROUND_RED |
756 FOREGROUND_GREEN | FOREGROUND_BLUE);
757 fprintf(fp, "%s()", fnc);
758 SetConsoleTextAttribute(GetStdHandle(
760 FOREGROUND_RED | FOREGROUND_GREEN |
764 fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s[T:"
765 EINA_COLOR_ORANGE "%lu" EINA_COLOR_RESET "] "
766 EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ",
767 color, name, eina_log_pid_get(), d->domain_str,
768 (unsigned long)cur, fnc);
774 eina_log_print_prefix_NOthreads_color_NOfile_func(fp,
781 fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s "
782 EINA_COLOR_HIGH "%s()" EINA_COLOR_RESET " ",
783 color, name, eina_log_pid_get(), d->domain_str, fnc);
788 eina_log_print_prefix_threads_color_file_NOfunc(FILE *fp,
789 const Eina_Log_Domain *d,
790 Eina_Log_Level level,
792 const char *fnc __UNUSED__,
797 DECLARE_LEVEL_NAME_COLOR(level);
802 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
804 fprintf(fp, "%s", name);
805 SetConsoleTextAttribute(GetStdHandle(
807 FOREGROUND_RED | FOREGROUND_GREEN |
810 SetConsoleTextAttribute(GetStdHandle(
812 eina_log_win32_color_get(d->domain_str));
813 fprintf(fp, "%s[T:", d->name);
814 SetConsoleTextAttribute(GetStdHandle(
816 FOREGROUND_RED | FOREGROUND_GREEN |
819 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
820 FOREGROUND_GREEN | FOREGROUND_BLUE);
821 fprintf(fp, "%lu", (unsigned long)cur);
822 SetConsoleTextAttribute(GetStdHandle(
824 FOREGROUND_RED | FOREGROUND_GREEN |
826 fprintf(fp, "] %s:%d ", file, line);
828 fprintf(fp, "%s%s<%u>" EINA_COLOR_RESET ":%s[T:"
829 EINA_COLOR_ORANGE "%lu" EINA_COLOR_RESET "] %s:%d ",
830 color, name, eina_log_pid_get(), d->domain_str,
831 (unsigned long)cur, file, line);
837 eina_log_print_prefix_NOthreads_color_file_NOfunc(fp,
844 fprintf(fp, "%s%s" EINA_COLOR_RESET ":%s %s:%d ",
845 color, name, d->domain_str, file, line);
848 #endif /* EFL_HAVE_THREADS */
850 static void (*_eina_log_print_prefix)(FILE *fp, const Eina_Log_Domain *d,
851 Eina_Log_Level level, const char *file,
854 eina_log_print_prefix_NOthreads_color_file_func;
857 eina_log_print_prefix_update(void)
859 if (_disable_file && _disable_function)
861 fprintf(stderr, "ERROR: cannot have " EINA_LOG_ENV_FILE_DISABLE " and "
862 EINA_LOG_ENV_FUNCTION_DISABLE " set at the same time, will "
863 "just disable function.\n");
867 #define S(NOthread, NOcolor, NOfile, NOfunc) \
868 _eina_log_print_prefix = \
869 eina_log_print_prefix_ ## NOthread ## threads_ ## NOcolor ## color_ ## \
871 ## file_ ## NOfunc ## func
873 #ifdef EFL_HAVE_THREADS
874 if (_threads_enabled)
880 else if (_disable_function)
889 else if (_disable_function)
904 else if (_disable_function)
913 else if (_disable_function)
923 * Creates a colored domain name string.
926 eina_log_domain_str_get(const char *name, const char *color)
935 name_len = strlen(name);
936 color_len = strlen(color);
938 malloc(sizeof(char) *
939 (color_len + name_len + strlen(EINA_COLOR_RESET) + 1));
943 memcpy((char *)d, color, color_len);
944 memcpy((char *)(d + color_len), name, name_len);
945 memcpy((char *)(d + color_len + name_len), EINA_COLOR_RESET,
946 strlen(EINA_COLOR_RESET));
947 ((char *)d)[color_len + name_len + strlen(EINA_COLOR_RESET)] = '\0';
956 * Setups a new logging domain to the name and color specified. Note that this
957 * constructor acts upon an pre-allocated object.
959 static Eina_Log_Domain *
960 eina_log_domain_new(Eina_Log_Domain *d, const char *name, const char *color)
962 EINA_SAFETY_ON_NULL_RETURN_VAL(d, NULL);
963 EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
965 d->level = EINA_LOG_LEVEL_UNKNOWN;
966 d->deleted = EINA_FALSE;
968 if ((color) && (!_disable_color))
969 d->domain_str = eina_log_domain_str_get(name, color);
971 d->domain_str = eina_log_domain_str_get(name, NULL);
973 d->name = strdup(name);
974 d->namelen = strlen(name);
980 * Frees internal strings of a log domain, keeping the log domain itself as a
981 * slot for next domain registers.
984 eina_log_domain_free(Eina_Log_Domain *d)
986 EINA_SAFETY_ON_NULL_RETURN(d);
989 free((char *)d->domain_str);
992 free((char *)d->name);
996 * Parses domain levels passed through the env var.
999 eina_log_domain_parse_pendings(void)
1003 if (!(start = getenv(EINA_LOG_ENV_LEVELS)))
1006 // name1:level1,name2:level2,name3:level3,...
1009 Eina_Log_Domain_Level_Pending *p;
1014 end = strchr(start, ':');
1018 // Parse level, keep going if failed
1019 level = strtol((char *)(end + 1), &tmp, 10);
1020 if (tmp == (end + 1))
1024 p = malloc(sizeof(Eina_Log_Domain_Level_Pending) + end - start + 1);
1028 p->namelen = end - start;
1029 memcpy((char *)p->name, start, end - start);
1030 ((char *)p->name)[end - start] = '\0';
1033 _pending_list = eina_inlist_append(_pending_list, EINA_INLIST_GET(p));
1036 start = strchr(tmp, ',');
1045 eina_log_domain_parse_pending_globs(void)
1049 if (!(start = getenv(EINA_LOG_ENV_LEVELS_GLOB)))
1052 // name1:level1,name2:level2,name3:level3,...
1055 Eina_Log_Domain_Level_Pending *p;
1060 end = strchr(start, ':');
1064 // Parse level, keep going if failed
1065 level = strtol((char *)(end + 1), &tmp, 10);
1066 if (tmp == (end + 1))
1070 p = malloc(sizeof(Eina_Log_Domain_Level_Pending) + end - start + 1);
1074 p->namelen = 0; /* not that useful */
1075 memcpy((char *)p->name, start, end - start);
1076 ((char *)p->name)[end - start] = '\0';
1079 _glob_list = eina_inlist_append(_glob_list, EINA_INLIST_GET(p));
1082 start = strchr(tmp, ',');
1091 eina_log_domain_register_unlocked(const char *name, const char *color)
1093 Eina_Log_Domain_Level_Pending *pending = NULL;
1097 for (i = 0; i < _log_domains_count; i++)
1099 if (_log_domains[i].deleted)
1101 // Found a flagged slot, free domain_str and replace slot
1102 eina_log_domain_new(&_log_domains[i], name, color);
1103 goto finish_register;
1107 if (_log_domains_count >= _log_domains_allocated)
1109 Eina_Log_Domain *tmp;
1113 // special case for init, eina itself will allocate a dozen of domains
1116 // grow 8 buckets to minimize reallocs
1117 size = _log_domains_allocated + 8;
1119 tmp = realloc(_log_domains, sizeof(Eina_Log_Domain) * size);
1125 _log_domains_allocated = size;
1131 // Use an allocated slot
1132 eina_log_domain_new(&_log_domains[i], name, color);
1133 _log_domains_count++;
1136 namelen = _log_domains[i].namelen;
1138 EINA_INLIST_FOREACH(_pending_list, pending)
1140 if ((namelen == pending->namelen) && (strcmp(pending->name, name) == 0))
1142 _log_domains[i].level = pending->level;
1144 eina_inlist_remove(_pending_list, EINA_INLIST_GET(pending));
1150 if (_log_domains[i].level == EINA_LOG_LEVEL_UNKNOWN)
1152 EINA_INLIST_FOREACH(_glob_list, pending)
1154 if (!fnmatch(pending->name, name, 0))
1156 _log_domains[i].level = pending->level;
1162 // Check if level is still UNKNOWN, set it to global
1163 if (_log_domains[i].level == EINA_LOG_LEVEL_UNKNOWN)
1164 _log_domains[i].level = _log_level;
1169 static inline Eina_Bool
1170 eina_log_term_color_supported(const char *term)
1180 /* list of known to support color terminals,
1181 * take from gentoo's portage.
1184 case 'x': /* xterm and xterm-color */
1185 return ((strncmp(tail, "term", sizeof("term") - 1) == 0) &&
1186 ((tail[sizeof("term") - 1] == '\0') ||
1187 (strcmp(tail + sizeof("term") - 1, "-color") == 0)));
1189 case 'E': /* Eterm */
1190 case 'a': /* aterm */
1191 case 'k': /* kterm */
1192 return (strcmp(tail, "term") == 0);
1194 case 'r': /* xrvt or rxvt-unicode */
1195 return ((strncmp(tail, "xvt", sizeof("xvt") - 1) == 0) &&
1196 ((tail[sizeof("xvt") - 1] == '\0') ||
1197 (strcmp(tail + sizeof("xvt") - 1, "-unicode") == 0)));
1199 case 's': /* screen */
1200 return (strcmp(tail, "creen") == 0);
1202 case 'g': /* gnome */
1203 return (strcmp(tail, "nome") == 0);
1205 case 'i': /* interix */
1206 return (strcmp(tail, "nterix") == 0);
1214 eina_log_domain_unregister_unlocked(int domain)
1218 if ((unsigned int)domain >= _log_domains_count)
1221 d = &_log_domains[domain];
1222 eina_log_domain_free(d);
1227 eina_log_print_unlocked(int domain,
1228 Eina_Log_Level level,
1237 #ifdef EINA_SAFETY_CHECKS
1238 if (EINA_UNLIKELY((unsigned int)domain >= _log_domains_count) ||
1239 EINA_UNLIKELY(domain < 0))
1241 if (file && fnc && fmt)
1244 "CRI: %s:%d %s() eina_log_print() unknown domain %d, original message format '%s'\n",
1253 "CRI: eina_log_print() unknown domain %d, original message format '%s'\n",
1257 if (_abort_on_critical)
1264 d = _log_domains + domain;
1265 #ifdef EINA_SAFETY_CHECKS
1266 if (EINA_UNLIKELY(d->deleted))
1269 "ERR: eina_log_print() domain %d is deleted\n",
1276 if (level > d->level)
1287 fprintf(stderr, "ERR: %s: can not allocate memory\n", __FUNCTION__);
1292 while (strchr(tmp, '%'))
1298 _print_cb(d, level, file, fnc, line, wfmt, _print_cb_data, args);
1302 _print_cb(d, level, file, fnc, line, fmt, _print_cb_data, args);
1305 if (EINA_UNLIKELY(_abort_on_critical) &&
1306 EINA_UNLIKELY(level <= _abort_level_on_critical))
1317 /*============================================================================*
1319 *============================================================================*/
1323 * @brief Initialize the log module.
1325 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
1327 * This function sets up the log module of Eina. It is called by
1332 * @warning Not-MT: just call this function from main thread! The
1333 * place where this function was called the first time is
1334 * considered the main thread.
1339 #ifdef EINA_ENABLE_LOG
1340 const char *level, *tmp;
1343 assert((sizeof(_names) / sizeof(_names[0])) == EINA_LOG_LEVELS);
1345 #ifdef EINA_LOG_BACKTRACE
1346 if ((tmp = getenv(EINA_LOG_ENV_BACKTRACE)))
1347 _backtrace_level = atoi(tmp);
1350 if ((tmp = getenv(EINA_LOG_ENV_COLOR_DISABLE)))
1351 color_disable = atoi(tmp);
1355 /* Check if color is explicitly disabled */
1356 if (color_disable == 1)
1357 _disable_color = EINA_TRUE;
1360 /* color was not explicitly disabled or enabled, guess it */
1361 else if (color_disable == -1)
1363 if (!eina_log_term_color_supported(getenv("TERM")))
1364 _disable_color = EINA_TRUE;
1367 /* if not a terminal, but redirected to a file, disable color */
1370 if (_print_cb == eina_log_print_cb_stderr)
1372 else if (_print_cb == eina_log_print_cb_stdout)
1377 if ((fd >= 0) && (!isatty(fd)))
1378 _disable_color = EINA_TRUE;
1383 if ((tmp = getenv(EINA_LOG_ENV_FILE_DISABLE)) && (atoi(tmp) == 1))
1384 _disable_file = EINA_TRUE;
1386 if ((tmp = getenv(EINA_LOG_ENV_FUNCTION_DISABLE)) && (atoi(tmp) == 1))
1387 _disable_function = EINA_TRUE;
1389 if ((tmp = getenv(EINA_LOG_ENV_ABORT)) && (atoi(tmp) == 1))
1390 _abort_on_critical = EINA_TRUE;
1392 if ((tmp = getenv(EINA_LOG_ENV_ABORT_LEVEL)))
1393 _abort_level_on_critical = atoi(tmp);
1395 eina_log_print_prefix_update();
1398 if ((level = getenv(EINA_LOG_ENV_LEVEL)))
1399 _log_level = atoi(level);
1401 // Register UNKNOWN domain, the default logger
1402 EINA_LOG_DOMAIN_GLOBAL = eina_log_domain_register("", NULL);
1404 if (EINA_LOG_DOMAIN_GLOBAL < 0)
1406 fprintf(stderr, "Failed to create global logging domain.\n");
1410 // Parse pending domains passed through EINA_LOG_LEVELS_GLOB
1411 eina_log_domain_parse_pending_globs();
1413 // Parse pending domains passed through EINA_LOG_LEVELS
1414 eina_log_domain_parse_pendings();
1422 * @brief Shut down the log module.
1424 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
1426 * This function shuts down the log module set up by
1427 * eina_log_init(). It is called by eina_shutdown().
1429 * @see eina_shutdown()
1431 * @warning Not-MT: just call this function from main thread! The
1432 * place where eina_log_init() (eina_init()) was called the
1433 * first time is considered the main thread.
1436 eina_log_shutdown(void)
1438 #ifdef EINA_ENABLE_LOG
1441 while (_log_domains_count--)
1443 if (_log_domains[_log_domains_count].deleted)
1446 eina_log_domain_free(&_log_domains[_log_domains_count]);
1451 _log_domains = NULL;
1452 _log_domains_count = 0;
1453 _log_domains_allocated = 0;
1458 _glob_list = _glob_list->next;
1462 while (_pending_list)
1464 tmp = _pending_list;
1465 _pending_list = _pending_list->next;
1473 #ifdef EFL_HAVE_THREADS
1477 * @brief Activate the log mutex.
1479 * This function activate the mutex in the eina log module. It is called by
1480 * eina_threads_init().
1482 * @see eina_threads_init()
1485 eina_log_threads_init(void)
1487 #ifdef EINA_ENABLE_LOG
1488 if (_threads_inited) return;
1489 _main_thread = SELF();
1490 if (!INIT()) return;
1491 _threads_inited = EINA_TRUE;
1497 * @brief Shut down the log mutex.
1499 * This function shuts down the mutex in the log module.
1500 * It is called by eina_threads_shutdown().
1502 * @see eina_threads_shutdown()
1505 eina_log_threads_shutdown(void)
1507 #ifdef EINA_ENABLE_LOG
1508 if (!_threads_inited) return;
1511 _threads_enabled = EINA_FALSE;
1512 _threads_inited = EINA_FALSE;
1518 /*============================================================================*
1520 *============================================================================*/
1526 EAPI int EINA_LOG_DOMAIN_GLOBAL = 0;
1533 eina_log_threads_enable(void)
1535 #if defined (EFL_HAVE_THREADS) && defined (EINA_ENABLE_LOG)
1536 if (_threads_enabled) return;
1537 if (!_threads_inited) eina_log_threads_init();
1538 _threads_enabled = EINA_TRUE;
1539 eina_log_print_prefix_update();
1544 eina_log_print_cb_set(Eina_Log_Print_Cb cb, void *data)
1546 #ifdef EINA_ENABLE_LOG
1549 _print_cb_data = data;
1550 eina_log_print_prefix_update();
1559 eina_log_level_set(int level)
1561 #ifdef EINA_ENABLE_LOG
1563 if (EINA_LIKELY((EINA_LOG_DOMAIN_GLOBAL >= 0) &&
1564 ((unsigned int)EINA_LOG_DOMAIN_GLOBAL < _log_domains_count)))
1565 _log_domains[EINA_LOG_DOMAIN_GLOBAL].level = level;
1572 eina_log_level_get(void)
1574 #ifdef EINA_ENABLE_LOG
1582 eina_log_main_thread_check(void)
1584 #if defined (EFL_HAVE_THREADS) && defined (EINA_ENABLE_LOG)
1585 return ((!_threads_enabled) || IS_MAIN(SELF()));
1592 eina_log_color_disable_set(Eina_Bool disabled)
1594 #ifdef EINA_ENABLE_LOG
1595 _disable_color = disabled;
1602 eina_log_color_disable_get(void)
1604 #ifdef EINA_ENABLE_LOG
1605 return _disable_color;
1612 eina_log_file_disable_set(Eina_Bool disabled)
1614 #ifdef EINA_ENABLE_LOG
1615 _disable_file = disabled;
1622 eina_log_file_disable_get(void)
1624 #ifdef EINA_ENABLE_LOG
1625 return _disable_file;
1632 eina_log_function_disable_set(Eina_Bool disabled)
1634 #ifdef EINA_ENABLE_LOG
1635 _disable_function = disabled;
1642 eina_log_function_disable_get(void)
1644 #ifdef EINA_ENABLE_LOG
1645 return _disable_function;
1652 eina_log_abort_on_critical_set(Eina_Bool abort_on_critical)
1654 #ifdef EINA_ENABLE_LOG
1655 _abort_on_critical = abort_on_critical;
1657 (void) abort_on_critical;
1662 eina_log_abort_on_critical_get(void)
1664 #ifdef EINA_ENABLE_LOG
1665 return _abort_on_critical;
1672 eina_log_abort_on_critical_level_set(int critical_level)
1674 #ifdef EINA_ENABLE_LOG
1675 _abort_level_on_critical = critical_level;
1677 (void) critical_level;
1682 eina_log_abort_on_critical_level_get(void)
1684 #ifdef EINA_ENABLE_LOG
1685 return _abort_level_on_critical;
1692 eina_log_domain_register(const char *name, const char *color)
1694 #ifdef EINA_ENABLE_LOG
1697 EINA_SAFETY_ON_NULL_RETURN_VAL(name, -1);
1700 r = eina_log_domain_register_unlocked(name, color);
1711 eina_log_domain_unregister(int domain)
1713 #ifdef EINA_ENABLE_LOG
1714 EINA_SAFETY_ON_FALSE_RETURN(domain >= 0);
1716 eina_log_domain_unregister_unlocked(domain);
1724 eina_log_domain_level_set(const char *domain_name, int level)
1726 #ifdef EINA_ENABLE_LOG
1727 Eina_Log_Domain_Level_Pending *pending;
1731 EINA_SAFETY_ON_NULL_RETURN(domain_name);
1733 namelen = strlen(domain_name);
1735 for (i = 0; i < _log_domains_count; i++)
1737 if (_log_domains[i].deleted)
1740 if ((namelen != _log_domains[i].namelen) ||
1741 (strcmp(_log_domains[i].name, domain_name) != 0))
1744 _log_domains[i].level = level;
1748 EINA_INLIST_FOREACH(_pending_list, pending)
1750 if ((namelen == pending->namelen) &&
1751 (strcmp(pending->name, domain_name) == 0))
1753 pending->level = level;
1758 pending = malloc(sizeof(Eina_Log_Domain_Level_Pending) + namelen + 1);
1762 pending->level = level;
1763 pending->namelen = namelen;
1764 memcpy(pending->name, domain_name, namelen + 1);
1766 _pending_list = eina_inlist_append(_pending_list, EINA_INLIST_GET(pending));
1774 eina_log_domain_level_get(const char *domain_name)
1776 #ifdef EINA_ENABLE_LOG
1777 Eina_Log_Domain_Level_Pending *pending;
1781 EINA_SAFETY_ON_NULL_RETURN_VAL(domain_name, EINA_LOG_LEVEL_UNKNOWN);
1783 namelen = strlen(domain_name);
1785 for (i = 0; i < _log_domains_count; i++)
1787 if (_log_domains[i].deleted)
1790 if ((namelen != _log_domains[i].namelen) ||
1791 (strcmp(_log_domains[i].name, domain_name) != 0))
1794 return _log_domains[i].level;
1797 EINA_INLIST_FOREACH(_pending_list, pending)
1799 if ((namelen == pending->namelen) &&
1800 (strcmp(pending->name, domain_name) == 0))
1801 return pending->level;
1804 EINA_INLIST_FOREACH(_glob_list, pending)
1806 if (!fnmatch(pending->name, domain_name, 0))
1807 return pending->level;
1818 eina_log_domain_registered_level_get(int domain)
1820 #ifdef EINA_ENABLE_LOG
1821 EINA_SAFETY_ON_FALSE_RETURN_VAL(domain >= 0, EINA_LOG_LEVEL_UNKNOWN);
1822 EINA_SAFETY_ON_FALSE_RETURN_VAL((unsigned int)domain < _log_domains_count,
1823 EINA_LOG_LEVEL_UNKNOWN);
1824 EINA_SAFETY_ON_TRUE_RETURN_VAL(_log_domains[domain].deleted,
1825 EINA_LOG_LEVEL_UNKNOWN);
1826 return _log_domains[domain].level;
1833 #ifdef EINA_LOG_BACKTRACE
1834 # define DISPLAY_BACKTRACE(File, Level) \
1835 if (EINA_UNLIKELY(Level < _backtrace_level)) \
1842 btlen = backtrace((void **)bt, 256); \
1843 strings = backtrace_symbols((void **)bt, btlen); \
1844 fprintf(File, "*** Backtrace ***\n"); \
1845 for (i = 0; i < btlen; ++i) \
1846 fprintf(File, "%s\n", strings[i]); \
1850 # define DISPLAY_BACKTRACE(File, Level)
1854 eina_log_print_cb_stderr(const Eina_Log_Domain *d,
1855 Eina_Log_Level level,
1860 __UNUSED__ void *data,
1863 #ifdef EINA_ENABLE_LOG
1864 _eina_log_print_prefix(stderr, d, level, file, fnc, line);
1865 vfprintf(stderr, fmt, args);
1867 DISPLAY_BACKTRACE(stderr, level);
1881 eina_log_print_cb_stdout(const Eina_Log_Domain *d,
1882 Eina_Log_Level level,
1887 __UNUSED__ void *data,
1890 #ifdef EINA_ENABLE_LOG
1891 _eina_log_print_prefix(stdout, d, level, file, fnc, line);
1894 DISPLAY_BACKTRACE(stdout, level);
1908 eina_log_print_cb_file(const Eina_Log_Domain *d,
1909 __UNUSED__ Eina_Log_Level level,
1917 #ifdef EINA_ENABLE_LOG
1919 #ifdef EFL_HAVE_THREADS
1920 if (_threads_enabled)
1927 fprintf(f, "%s[T:%lu] %s:%d %s() ", d->name, (unsigned long)cur,
1934 fprintf(f, "%s<%u> %s:%d %s() ", d->name, eina_log_pid_get(),
1936 DISPLAY_BACKTRACE(f, level);
1937 #ifdef EFL_HAVE_THREADS
1940 vfprintf(f, fmt, args);
1954 eina_log_print(int domain, Eina_Log_Level level, const char *file,
1955 const char *fnc, int line, const char *fmt, ...)
1957 #ifdef EINA_ENABLE_LOG
1960 #ifdef EINA_SAFETY_CHECKS
1961 if (EINA_UNLIKELY(!file))
1963 fputs("ERR: eina_log_print() file == NULL\n", stderr);
1967 if (EINA_UNLIKELY(!fnc))
1969 fputs("ERR: eina_log_print() fnc == NULL\n", stderr);
1973 if (EINA_UNLIKELY(!fmt))
1975 fputs("ERR: eina_log_print() fmt == NULL\n", stderr);
1980 va_start(args, fmt);
1982 eina_log_print_unlocked(domain, level, file, fnc, line, fmt, args);
1996 eina_log_vprint(int domain, Eina_Log_Level level, const char *file,
1997 const char *fnc, int line, const char *fmt, va_list args)
1999 #ifdef EINA_ENABLE_LOG
2001 #ifdef EINA_SAFETY_CHECKS
2002 if (EINA_UNLIKELY(!file))
2004 fputs("ERR: eina_log_print() file == NULL\n", stderr);
2008 if (EINA_UNLIKELY(!fnc))
2010 fputs("ERR: eina_log_print() fnc == NULL\n", stderr);
2014 if (EINA_UNLIKELY(!fmt))
2016 fputs("ERR: eina_log_print() fmt == NULL\n", stderr);
2022 eina_log_print_unlocked(domain, level, file, fnc, line, fmt, args);