1 /* GLIB - Library of useful routines for C programming
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GLib Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GLib Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GLib at ftp://ftp.gtk.org/pub/gtk/.
47 #include "gprintfint.h"
50 typedef FILE* GFileDescriptor;
52 typedef gint GFileDescriptor;
55 /* --- structures --- */
56 typedef struct _GLogDomain GLogDomain;
57 typedef struct _GLogHandler GLogHandler;
61 GLogLevelFlags fatal_mask;
62 GLogHandler *handlers;
68 GLogLevelFlags log_level;
75 /* --- variables --- */
76 static GMutex *g_messages_lock = NULL;
77 static GLogDomain *g_log_domains = NULL;
78 static GLogLevelFlags g_log_always_fatal = G_LOG_FATAL_MASK;
79 static GPrintFunc glib_print_func = NULL;
80 static GPrintFunc glib_printerr_func = NULL;
81 static GPrivate *g_log_depth = NULL;
82 static GLogLevelFlags g_log_msg_prefix = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_DEBUG;
85 /* --- functions --- */
90 # include <process.h> /* For _getpid() */
91 static gboolean alloc_console_called = FALSE;
92 static gboolean win32_keep_fatal_message = FALSE;
94 /* This default message will usually be overwritten. */
95 /* Yes, a fixed size buffer is bad. So sue me. But g_error is never
96 * with huge strings, is it?
98 static gchar fatal_msg_buf[1000] = "Unspecified fatal error encountered, aborting.";
99 static gchar *fatal_msg_ptr = fatal_msg_buf;
101 /* Just use stdio. If we're out of memory, we're hosed anyway. */
104 dowrite (GFileDescriptor fd,
108 if (win32_keep_fatal_message)
110 memcpy (fatal_msg_ptr, buf, len);
111 fatal_msg_ptr += len;
116 fwrite (buf, len, 1, fd);
121 #define write(fd, buf, len) dowrite(fd, buf, len)
124 ensure_stdout_valid (void)
128 if (win32_keep_fatal_message)
131 if (!alloc_console_called)
133 handle = GetStdHandle (STD_OUTPUT_HANDLE);
135 if (handle == INVALID_HANDLE_VALUE)
138 alloc_console_called = TRUE;
139 freopen ("CONOUT$", "w", stdout);
144 #define ensure_stdout_valid() /* Define as empty */
148 write_string (GFileDescriptor fd,
151 write (fd, string, strlen (string));
155 g_messages_prefixed_init (void)
157 static gboolean initialized = FALSE;
164 val = g_getenv ("G_MESSAGES_PREFIXED");
168 static const GDebugKey keys[] = {
169 { "error", G_LOG_LEVEL_ERROR },
170 { "critical", G_LOG_LEVEL_CRITICAL },
171 { "warning", G_LOG_LEVEL_WARNING },
172 { "message", G_LOG_LEVEL_MESSAGE },
173 { "info", G_LOG_LEVEL_INFO },
174 { "debug", G_LOG_LEVEL_DEBUG }
177 g_log_msg_prefix = g_parse_debug_string (val, keys, G_N_ELEMENTS (keys));
183 g_log_find_domain_L (const gchar *log_domain)
185 register GLogDomain *domain;
187 domain = g_log_domains;
190 if (strcmp (domain->log_domain, log_domain) == 0)
192 domain = domain->next;
198 g_log_domain_new_L (const gchar *log_domain)
200 register GLogDomain *domain;
202 domain = g_new (GLogDomain, 1);
203 domain->log_domain = g_strdup (log_domain);
204 domain->fatal_mask = G_LOG_FATAL_MASK;
205 domain->handlers = NULL;
207 domain->next = g_log_domains;
208 g_log_domains = domain;
214 g_log_domain_check_free_L (GLogDomain *domain)
216 if (domain->fatal_mask == G_LOG_FATAL_MASK &&
217 domain->handlers == NULL)
219 register GLogDomain *last, *work;
223 work = g_log_domains;
229 last->next = domain->next;
231 g_log_domains = domain->next;
232 g_free (domain->log_domain);
243 g_log_domain_get_handler_L (GLogDomain *domain,
244 GLogLevelFlags log_level,
247 if (domain && log_level)
249 register GLogHandler *handler;
251 handler = domain->handlers;
254 if ((handler->log_level & log_level) == log_level)
256 *data = handler->data;
257 return handler->log_func;
259 handler = handler->next;
262 return g_log_default_handler;
266 g_log_set_always_fatal (GLogLevelFlags fatal_mask)
268 GLogLevelFlags old_mask;
270 /* restrict the global mask to levels that are known to glib
271 * since this setting applies to all domains
273 fatal_mask &= (1 << G_LOG_LEVEL_USER_SHIFT) - 1;
274 /* force errors to be fatal */
275 fatal_mask |= G_LOG_LEVEL_ERROR;
276 /* remove bogus flag */
277 fatal_mask &= ~G_LOG_FLAG_FATAL;
279 g_mutex_lock (g_messages_lock);
280 old_mask = g_log_always_fatal;
281 g_log_always_fatal = fatal_mask;
282 g_mutex_unlock (g_messages_lock);
288 g_log_set_fatal_mask (const gchar *log_domain,
289 GLogLevelFlags fatal_mask)
291 GLogLevelFlags old_flags;
292 register GLogDomain *domain;
297 /* force errors to be fatal */
298 fatal_mask |= G_LOG_LEVEL_ERROR;
299 /* remove bogus flag */
300 fatal_mask &= ~G_LOG_FLAG_FATAL;
302 g_mutex_lock (g_messages_lock);
304 domain = g_log_find_domain_L (log_domain);
306 domain = g_log_domain_new_L (log_domain);
307 old_flags = domain->fatal_mask;
309 domain->fatal_mask = fatal_mask;
310 g_log_domain_check_free_L (domain);
312 g_mutex_unlock (g_messages_lock);
318 g_log_set_handler (const gchar *log_domain,
319 GLogLevelFlags log_levels,
323 static guint handler_id = 0;
325 GLogHandler *handler;
327 g_return_val_if_fail ((log_levels & G_LOG_LEVEL_MASK) != 0, 0);
328 g_return_val_if_fail (log_func != NULL, 0);
333 handler = g_new (GLogHandler, 1);
335 g_mutex_lock (g_messages_lock);
337 domain = g_log_find_domain_L (log_domain);
339 domain = g_log_domain_new_L (log_domain);
341 handler->id = ++handler_id;
342 handler->log_level = log_levels;
343 handler->log_func = log_func;
344 handler->data = user_data;
345 handler->next = domain->handlers;
346 domain->handlers = handler;
348 g_mutex_unlock (g_messages_lock);
354 g_log_remove_handler (const gchar *log_domain,
357 register GLogDomain *domain;
359 g_return_if_fail (handler_id > 0);
364 g_mutex_lock (g_messages_lock);
365 domain = g_log_find_domain_L (log_domain);
368 GLogHandler *work, *last;
371 work = domain->handlers;
374 if (work->id == handler_id)
377 last->next = work->next;
379 domain->handlers = work->next;
380 g_log_domain_check_free_L (domain);
381 g_mutex_unlock (g_messages_lock);
389 g_mutex_unlock (g_messages_lock);
390 g_warning ("%s: could not find handler with id `%d' for domain \"%s\"",
391 G_STRLOC, handler_id, log_domain);
395 g_logv (const gchar *log_domain,
396 GLogLevelFlags log_level,
401 gboolean was_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
402 gboolean was_recursion = (log_level & G_LOG_FLAG_RECURSION) != 0;
405 log_level &= G_LOG_LEVEL_MASK;
409 /* we use a stack buffer of fixed size, because we might get called
412 _g_vsnprintf (buffer, 1024, format, args1);
414 for (i = g_bit_nth_msf (log_level, -1); i >= 0; i = g_bit_nth_msf (log_level, i))
416 register GLogLevelFlags test_level;
419 if (log_level & test_level)
421 guint depth = GPOINTER_TO_UINT (g_private_get (g_log_depth));
424 guint domain_fatal_mask;
425 gpointer data = NULL;
428 test_level |= G_LOG_FLAG_FATAL;
430 test_level |= G_LOG_FLAG_RECURSION;
432 /* check recursion and lookup handler */
433 g_mutex_lock (g_messages_lock);
434 domain = g_log_find_domain_L (log_domain ? log_domain : "");
436 test_level |= G_LOG_FLAG_RECURSION;
438 domain_fatal_mask = domain ? domain->fatal_mask : G_LOG_FATAL_MASK;
439 if ((domain_fatal_mask | g_log_always_fatal) & test_level)
440 test_level |= G_LOG_FLAG_FATAL;
441 if (test_level & G_LOG_FLAG_RECURSION)
442 log_func = _g_log_fallback_handler;
444 log_func = g_log_domain_get_handler_L (domain, test_level, &data);
446 g_mutex_unlock (g_messages_lock);
448 g_private_set (g_log_depth, GUINT_TO_POINTER (depth));
450 /* had to defer debug initialization until we can keep track of recursion */
451 if (!(test_level & G_LOG_FLAG_RECURSION) && !_g_debug_initialized)
453 guint orig_test_level = test_level;
456 if ((domain_fatal_mask | g_log_always_fatal) & test_level)
457 test_level |= G_LOG_FLAG_FATAL;
458 if (test_level != orig_test_level)
460 /* need a relookup, not nice, but not too bad either */
461 g_mutex_lock (g_messages_lock);
462 domain = g_log_find_domain_L (log_domain ? log_domain : "");
463 log_func = g_log_domain_get_handler_L (domain, test_level, &data);
465 g_mutex_unlock (g_messages_lock);
469 log_func (log_domain, test_level, buffer, data);
471 if (test_level & G_LOG_FLAG_FATAL)
474 MessageBox (NULL, fatal_msg_buf, NULL, MB_OK);
476 #if defined (G_ENABLE_DEBUG) && (defined (SIGTRAP) || defined (G_OS_WIN32))
477 if (!(test_level & G_LOG_FLAG_RECURSION))
481 #else /* !G_ENABLE_DEBUG || !(SIGTRAP || G_OS_WIN32) */
483 #endif /* !G_ENABLE_DEBUG || !(SIGTRAP || G_OS_WIN32) */
487 g_private_set (g_log_depth, GUINT_TO_POINTER (depth));
493 g_log (const gchar *log_domain,
494 GLogLevelFlags log_level,
500 va_start (args, format);
501 g_logv (log_domain, log_level, format, args);
506 strdup_convert (const gchar *string,
507 const gchar *charset)
509 if (!g_utf8_validate (string, -1, NULL))
510 return g_strconcat ("[Invalid UTF-8] ", string, NULL);
515 gchar *result = g_convert_with_fallback (string, -1, charset, "UTF-8", "?", NULL, NULL, &err);
520 /* Not thread-safe, but doesn't matter if we print the warning twice
522 static gboolean warned = FALSE;
526 _g_fprintf (stderr, "GLib: Cannot convert message: %s\n", err->message);
530 return g_strdup (string);
535 /* For a radix of 8 we need at most 3 output bytes for 1 input
536 * byte. Additionally we might need up to 2 output bytes for the
537 * readix prefix and 1 byte for the trailing NULL.
539 #define FORMAT_UNSIGNED_BUFSIZE ((GLIB_SIZEOF_LONG * 3) + 3)
542 format_unsigned (gchar *buf,
550 /* we may not call _any_ GLib functions here (or macros like g_return_if_fail()) */
552 if (radix != 8 && radix != 10 && radix != 16)
585 /* Again we can't use g_assert; actually this check should _never_ fail. */
586 if (n > FORMAT_UNSIGNED_BUFSIZE - 3)
599 buf[i] = c + 'a' - 10;
606 /* string size big enough to hold level prefix */
607 #define STRING_BUFFER_SIZE (FORMAT_UNSIGNED_BUFSIZE + 32)
609 #define ALERT_LEVELS (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING)
611 static GFileDescriptor
612 mklevel_prefix (gchar level_prefix[STRING_BUFFER_SIZE],
615 gboolean to_stdout = TRUE;
617 /* we may not call _any_ GLib functions here */
619 switch (log_level & G_LOG_LEVEL_MASK)
621 case G_LOG_LEVEL_ERROR:
622 strcpy (level_prefix, "ERROR");
625 case G_LOG_LEVEL_CRITICAL:
626 strcpy (level_prefix, "CRITICAL");
629 case G_LOG_LEVEL_WARNING:
630 strcpy (level_prefix, "WARNING");
633 case G_LOG_LEVEL_MESSAGE:
634 strcpy (level_prefix, "Message");
637 case G_LOG_LEVEL_INFO:
638 strcpy (level_prefix, "INFO");
640 case G_LOG_LEVEL_DEBUG:
641 strcpy (level_prefix, "DEBUG");
646 strcpy (level_prefix, "LOG-");
647 format_unsigned (level_prefix + 4, log_level & G_LOG_LEVEL_MASK, 16);
650 strcpy (level_prefix, "LOG");
653 if (log_level & G_LOG_FLAG_RECURSION)
654 strcat (level_prefix, " (recursed)");
655 if (log_level & ALERT_LEVELS)
656 strcat (level_prefix, " **");
658 ensure_stdout_valid ();
660 win32_keep_fatal_message = (log_level & G_LOG_FLAG_FATAL) != 0;
661 /* Use just stdout as stderr is hard to get redirected from the DOS prompt. */
664 return to_stdout ? 1 : 2;
669 _g_log_fallback_handler (const gchar *log_domain,
670 GLogLevelFlags log_level,
671 const gchar *message,
672 gpointer unused_data)
674 gchar level_prefix[STRING_BUFFER_SIZE], pid_string[FORMAT_UNSIGNED_BUFSIZE];
675 gboolean is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
678 /* we can not call _any_ GLib functions in this fallback handler,
679 * which is why we skip UTF-8 conversion, etc.
680 * since we either recursed or ran out of memory, we're in a pretty
681 * pathologic situation anyways, what we can do is giving the
682 * the process ID unconditionally however.
685 fd = mklevel_prefix (level_prefix, log_level);
687 message = "(NULL) message";
689 format_unsigned (pid_string, getpid (), 10);
692 write_string (fd, "\n");
694 write_string (fd, "\n** ");
695 write_string (fd, "(process:");
696 write_string (fd, pid_string);
697 write_string (fd, "): ");
700 write_string (fd, log_domain);
701 write_string (fd, "-");
703 write_string (fd, level_prefix);
704 write_string (fd, ": ");
705 write_string (fd, message);
707 write_string (fd, "\naborting...\n");
709 write_string (fd, "\n");
713 g_log_default_handler (const gchar *log_domain,
714 GLogLevelFlags log_level,
715 const gchar *message,
716 gpointer unused_data)
718 gboolean is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
719 gchar level_prefix[STRING_BUFFER_SIZE], *string;
723 /* we can be called externally with recursion for whatever reason */
724 if (log_level & G_LOG_FLAG_RECURSION)
726 _g_log_fallback_handler (log_domain, log_level, message, unused_data);
730 g_messages_prefixed_init ();
732 fd = mklevel_prefix (level_prefix, log_level);
734 gstring = g_string_new ("");
735 if (log_level & ALERT_LEVELS)
736 g_string_append (gstring, "\n");
738 g_string_append (gstring, "** ");
740 if ((g_log_msg_prefix & log_level) == log_level)
742 const gchar *prg_name = g_get_prgname ();
745 g_string_append_printf (gstring, "(process:%lu): ", (gulong)getpid ());
747 g_string_append_printf (gstring, "(%s:%lu): ", prg_name, (gulong)getpid ());
752 g_string_append (gstring, log_domain);
753 g_string_append_c (gstring, '-');
755 g_string_append (gstring, level_prefix);
757 g_string_append (gstring, ": ");
759 g_string_append (gstring, "(NULL) message");
762 const gchar *charset;
764 if (g_get_charset (&charset))
765 g_string_append (gstring, message); /* charset is UTF-8 already */
768 string = strdup_convert (message, charset);
769 g_string_append (gstring, string);
774 g_string_append (gstring, "\naborting...\n");
776 g_string_append (gstring, "\n");
778 string = g_string_free (gstring, FALSE);
780 write_string (fd, string);
785 g_set_print_handler (GPrintFunc func)
787 GPrintFunc old_print_func;
789 g_mutex_lock (g_messages_lock);
790 old_print_func = glib_print_func;
791 glib_print_func = func;
792 g_mutex_unlock (g_messages_lock);
794 return old_print_func;
798 g_print (const gchar *format,
803 GPrintFunc local_glib_print_func;
805 g_return_if_fail (format != NULL);
807 va_start (args, format);
808 string = g_strdup_vprintf (format, args);
811 g_mutex_lock (g_messages_lock);
812 local_glib_print_func = glib_print_func;
813 g_mutex_unlock (g_messages_lock);
815 if (local_glib_print_func)
816 local_glib_print_func (string);
819 const gchar *charset;
821 ensure_stdout_valid ();
822 if (g_get_charset (&charset))
823 fputs (string, stdout); /* charset is UTF-8 already */
826 gchar *lstring = strdup_convert (string, charset);
828 fputs (lstring, stdout);
837 g_set_printerr_handler (GPrintFunc func)
839 GPrintFunc old_printerr_func;
841 g_mutex_lock (g_messages_lock);
842 old_printerr_func = glib_printerr_func;
843 glib_printerr_func = func;
844 g_mutex_unlock (g_messages_lock);
846 return old_printerr_func;
850 g_printerr (const gchar *format,
855 GPrintFunc local_glib_printerr_func;
857 g_return_if_fail (format != NULL);
859 va_start (args, format);
860 string = g_strdup_vprintf (format, args);
863 g_mutex_lock (g_messages_lock);
864 local_glib_printerr_func = glib_printerr_func;
865 g_mutex_unlock (g_messages_lock);
867 if (local_glib_printerr_func)
868 local_glib_printerr_func (string);
871 const gchar *charset;
873 if (g_get_charset (&charset))
874 fputs (string, stderr); /* charset is UTF-8 already */
877 gchar *lstring = strdup_convert (string, charset);
879 fputs (lstring, stderr);
888 g_printf_string_upper_bound (const gchar *format,
892 return _g_vsnprintf (&c, 1, format, args) + 1;
896 g_messages_init (void)
898 g_messages_lock = g_mutex_new ();
899 g_log_depth = g_private_new (NULL);
900 g_messages_prefixed_init ();
904 gboolean _g_debug_initialized = FALSE;
905 guint _g_debug_flags = 0;
912 _g_debug_initialized = TRUE;
914 val = g_getenv ("G_DEBUG");
917 static const GDebugKey keys[] = {
918 {"fatal_warnings", G_DEBUG_FATAL_WARNINGS}
921 _g_debug_flags = g_parse_debug_string (val, keys, G_N_ELEMENTS (keys));
924 if (_g_debug_flags & G_DEBUG_FATAL_WARNINGS)
926 GLogLevelFlags fatal_mask;
928 fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
929 fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
930 g_log_set_always_fatal (fatal_mask);