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 Library 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 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library 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-1999. 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/.
48 /* Just use stdio. If we're out of memory, we're hosed anyway. */
56 fwrite (buf
, len
, 1, fd
);
62 ensure_stdout_valid (void)
66 handle
= GetStdHandle (STD_OUTPUT_HANDLE
);
68 if (handle
== INVALID_HANDLE_VALUE
)
71 freopen ("CONOUT$", "w", stdout
);
75 #define ensure_stdout_valid() /* Define as empty */
79 /* --- structures --- */
80 typedef struct _GLogDomain GLogDomain
;
81 typedef struct _GLogHandler GLogHandler
;
85 GLogLevelFlags fatal_mask
;
86 GLogHandler
*handlers
;
92 GLogLevelFlags log_level
;
99 /* --- variables --- */
101 static GMutex
* g_messages_lock
= NULL
;
103 const gchar
*g_log_domain_glib
= "GLib";
104 static GLogDomain
*g_log_domains
= NULL
;
105 static GLogLevelFlags g_log_always_fatal
= G_LOG_FATAL_MASK
;
106 static GPrintFunc glib_print_func
= NULL
;
107 static GPrintFunc glib_printerr_func
= NULL
;
108 static GErrorFunc glib_error_func
= NULL
;
109 static GWarningFunc glib_warning_func
= NULL
;
110 static GPrintFunc glib_message_func
= NULL
;
112 static GPrivate
* g_log_depth
= NULL
;
115 /* --- functions --- */
116 static inline GLogDomain
*
117 g_log_find_domain (const gchar
*log_domain
)
119 register GLogDomain
*domain
;
121 g_mutex_lock (g_messages_lock
);
122 domain
= g_log_domains
;
125 if (strcmp (domain
->log_domain
, log_domain
) == 0)
127 g_mutex_unlock (g_messages_lock
);
130 domain
= domain
->next
;
132 g_mutex_unlock (g_messages_lock
);
136 static inline GLogDomain
*
137 g_log_domain_new (const gchar
*log_domain
)
139 register GLogDomain
*domain
;
141 domain
= g_new (GLogDomain
, 1);
142 domain
->log_domain
= g_strdup (log_domain
);
143 domain
->fatal_mask
= G_LOG_FATAL_MASK
;
144 domain
->handlers
= NULL
;
146 g_mutex_lock (g_messages_lock
);
147 domain
->next
= g_log_domains
;
148 g_log_domains
= domain
;
149 g_mutex_unlock (g_messages_lock
);
155 g_log_domain_check_free (GLogDomain
*domain
)
157 if (domain
->fatal_mask
== G_LOG_FATAL_MASK
&&
158 domain
->handlers
== NULL
)
160 register GLogDomain
*last
, *work
;
164 g_mutex_lock (g_messages_lock
);
165 work
= g_log_domains
;
171 last
->next
= domain
->next
;
173 g_log_domains
= domain
->next
;
174 g_free (domain
->log_domain
);
181 g_mutex_unlock (g_messages_lock
);
185 static inline GLogFunc
186 g_log_domain_get_handler (GLogDomain
*domain
,
187 GLogLevelFlags log_level
,
190 if (domain
&& log_level
)
192 register GLogHandler
*handler
;
194 handler
= domain
->handlers
;
197 if ((handler
->log_level
& log_level
) == log_level
)
199 *data
= handler
->data
;
200 return handler
->log_func
;
202 handler
= handler
->next
;
205 return g_log_default_handler
;
209 g_log_set_always_fatal (GLogLevelFlags fatal_mask
)
211 GLogLevelFlags old_mask
;
213 /* restrict the global mask to levels that are known to glib */
214 fatal_mask
&= (1 << G_LOG_LEVEL_USER_SHIFT
) - 1;
215 /* force errors to be fatal */
216 fatal_mask
|= G_LOG_LEVEL_ERROR
;
217 /* remove bogus flag */
218 fatal_mask
&= ~G_LOG_FLAG_FATAL
;
220 g_mutex_lock (g_messages_lock
);
221 old_mask
= g_log_always_fatal
;
222 g_log_always_fatal
= fatal_mask
;
223 g_mutex_unlock (g_messages_lock
);
229 g_log_set_fatal_mask (const gchar
*log_domain
,
230 GLogLevelFlags fatal_mask
)
232 GLogLevelFlags old_flags
;
233 register GLogDomain
*domain
;
238 /* force errors to be fatal */
239 fatal_mask
|= G_LOG_LEVEL_ERROR
;
240 /* remove bogus flag */
241 fatal_mask
&= ~G_LOG_FLAG_FATAL
;
243 domain
= g_log_find_domain (log_domain
);
245 domain
= g_log_domain_new (log_domain
);
246 old_flags
= domain
->fatal_mask
;
248 domain
->fatal_mask
= fatal_mask
;
249 g_log_domain_check_free (domain
);
255 g_log_set_handler (const gchar
*log_domain
,
256 GLogLevelFlags log_levels
,
260 register GLogDomain
*domain
;
261 register GLogHandler
*handler
;
262 static guint handler_id
= 0;
264 g_return_val_if_fail ((log_levels
& G_LOG_LEVEL_MASK
) != 0, 0);
265 g_return_val_if_fail (log_func
!= NULL
, 0);
270 domain
= g_log_find_domain (log_domain
);
272 domain
= g_log_domain_new (log_domain
);
274 handler
= g_new (GLogHandler
, 1);
275 g_mutex_lock (g_messages_lock
);
276 handler
->id
= ++handler_id
;
277 g_mutex_unlock (g_messages_lock
);
278 handler
->log_level
= log_levels
;
279 handler
->log_func
= log_func
;
280 handler
->data
= user_data
;
281 handler
->next
= domain
->handlers
;
282 domain
->handlers
= handler
;
288 g_log_remove_handler (const gchar
*log_domain
,
291 register GLogDomain
*domain
;
293 g_return_if_fail (handler_id
> 0);
298 domain
= g_log_find_domain (log_domain
);
301 register GLogHandler
*work
, *last
;
304 work
= domain
->handlers
;
307 if (work
->id
== handler_id
)
310 last
->next
= work
->next
;
312 domain
->handlers
= work
->next
;
314 g_log_domain_check_free (domain
);
321 g_warning ("g_log_remove_handler(): could not find handler with id `%d' for domain \"%s\"",
327 g_logv (const gchar
*log_domain
,
328 GLogLevelFlags log_level
,
336 log_level
&= G_LOG_LEVEL_MASK
;
340 /* we use a stack buffer of fixed size, because we might get called
343 G_VA_COPY (args2
, args1
);
344 if (g_printf_string_upper_bound (format
, args1
) < 1024)
345 vsprintf (buffer
, format
, args2
);
348 /* since we might be out of memory, we can't use g_vsnprintf(). */
349 #ifdef HAVE_VSNPRINTF
350 vsnprintf (buffer
, 1024, format
, args2
);
351 #else /* !HAVE_VSNPRINTF */
352 /* we are out of luck here */
353 strncpy (buffer
, format
, 1024);
354 #endif /* !HAVE_VSNPRINTF */
359 for (i
= g_bit_nth_msf (log_level
, -1); i
>= 0; i
= g_bit_nth_msf (log_level
, i
))
361 register GLogLevelFlags test_level
;
364 if (log_level
& test_level
)
366 guint depth
= GPOINTER_TO_UINT (g_private_get (g_log_depth
));
369 gpointer data
= NULL
;
371 domain
= g_log_find_domain (log_domain
? log_domain
: "");
374 test_level
|= G_LOG_FLAG_RECURSION
;
377 g_private_set (g_log_depth
, GUINT_TO_POINTER (depth
));
379 g_mutex_lock (g_messages_lock
);
380 if ((((domain
? domain
->fatal_mask
: G_LOG_FATAL_MASK
) |
381 g_log_always_fatal
) & test_level
) != 0)
382 test_level
|= G_LOG_FLAG_FATAL
;
383 g_mutex_unlock (g_messages_lock
);
385 log_func
= g_log_domain_get_handler (domain
, test_level
, &data
);
386 log_func (log_domain
, test_level
, buffer
, data
);
388 /* *domain can be cluttered now */
390 if (test_level
& G_LOG_FLAG_FATAL
)
394 g_private_set (g_log_depth
, GUINT_TO_POINTER (depth
));
400 g_log (const gchar
*log_domain
,
401 GLogLevelFlags log_level
,
407 va_start (args
, format
);
408 g_logv (log_domain
, log_level
, format
, args
);
413 g_log_default_handler (const gchar
*log_domain
,
414 GLogLevelFlags log_level
,
415 const gchar
*message
,
416 gpointer unused_data
)
423 gboolean in_recursion
;
425 GErrorFunc local_glib_error_func
;
426 GWarningFunc local_glib_warning_func
;
427 GPrintFunc local_glib_message_func
;
429 in_recursion
= (log_level
& G_LOG_FLAG_RECURSION
) != 0;
430 is_fatal
= (log_level
& G_LOG_FLAG_FATAL
) != 0;
431 log_level
&= G_LOG_LEVEL_MASK
;
434 message
= "g_log_default_handler(): (NULL) message";
437 /* Use just stdout as stderr is hard to get redirected from the
442 fd
= (log_level
>= G_LOG_LEVEL_MESSAGE
) ? 1 : 2;
445 g_mutex_lock (g_messages_lock
);
446 local_glib_error_func
= glib_error_func
;
447 local_glib_warning_func
= glib_warning_func
;
448 local_glib_message_func
= glib_message_func
;
449 g_mutex_unlock (g_messages_lock
);
453 case G_LOG_LEVEL_ERROR
:
454 if (!log_domain
&& local_glib_error_func
)
456 /* compatibility code */
457 local_glib_error_func (message
);
460 /* use write(2) for output, in case we are out of memeory */
461 ensure_stdout_valid ();
465 write (fd
, log_domain
, strlen (log_domain
));
469 write (fd
, "\n** ", 4);
471 write (fd
, "ERROR (recursed) **: ", 21);
473 write (fd
, "ERROR **: ", 10);
474 write (fd
, message
, strlen(message
));
476 write (fd
, "\naborting...\n", 13);
480 case G_LOG_LEVEL_CRITICAL
:
481 ensure_stdout_valid ();
485 write (fd
, log_domain
, strlen (log_domain
));
489 write (fd
, "\n** ", 4);
491 write (fd
, "CRITICAL (recursed) **: ", 24);
493 write (fd
, "CRITICAL **: ", 13);
494 write (fd
, message
, strlen(message
));
496 write (fd
, "\naborting...\n", 13);
500 case G_LOG_LEVEL_WARNING
:
501 if (!log_domain
&& local_glib_warning_func
)
503 /* compatibility code */
504 local_glib_warning_func (message
);
507 ensure_stdout_valid ();
511 write (fd
, log_domain
, strlen (log_domain
));
515 write (fd
, "\n** ", 4);
517 write (fd
, "WARNING (recursed) **: ", 23);
519 write (fd
, "WARNING **: ", 12);
520 write (fd
, message
, strlen(message
));
522 write (fd
, "\naborting...\n", 13);
526 case G_LOG_LEVEL_MESSAGE
:
527 if (!log_domain
&& local_glib_message_func
)
529 /* compatibility code */
530 local_glib_message_func (message
);
533 ensure_stdout_valid ();
536 write (fd
, log_domain
, strlen (log_domain
));
540 write (fd
, "Message (recursed): ", 20);
542 write (fd
, "Message: ", 9);
543 write (fd
, message
, strlen(message
));
545 write (fd
, "\naborting...\n", 13);
549 case G_LOG_LEVEL_INFO
:
550 ensure_stdout_valid ();
553 write (fd
, log_domain
, strlen (log_domain
));
557 write (fd
, "INFO (recursed): ", 17);
559 write (fd
, "INFO: ", 6);
560 write (fd
, message
, strlen(message
));
562 write (fd
, "\naborting...\n", 13);
566 case G_LOG_LEVEL_DEBUG
:
567 ensure_stdout_valid ();
570 write (fd
, log_domain
, strlen (log_domain
));
574 write (fd
, "DEBUG (recursed): ", 18);
576 write (fd
, "DEBUG: ", 7);
577 write (fd
, message
, strlen(message
));
579 write (fd
, "\naborting...\n", 13);
584 /* we are used for a log level that is not defined by GLib itself,
585 * try to make the best out of it.
587 ensure_stdout_valid ();
590 write (fd
, log_domain
, strlen (log_domain
));
592 write (fd
, "-LOG (recursed:", 15);
594 write (fd
, "-LOG (", 6);
596 else if (in_recursion
)
597 write (fd
, "LOG (recursed:", 14);
599 write (fd
, "LOG (", 5);
602 gchar string
[] = "0x00): ";
603 gchar
*p
= string
+ 2;
606 i
= g_bit_nth_msf (log_level
, -1);
609 *p
= '0' + (i
& 0xf);
613 write (fd
, string
, 7);
616 write (fd
, "): ", 3);
617 write (fd
, message
, strlen(message
));
619 write (fd
, "\naborting...\n", 13);
627 g_set_print_handler (GPrintFunc func
)
629 GPrintFunc old_print_func
;
631 g_mutex_lock (g_messages_lock
);
632 old_print_func
= glib_print_func
;
633 glib_print_func
= func
;
634 g_mutex_unlock (g_messages_lock
);
636 return old_print_func
;
640 g_print (const gchar
*format
,
645 GPrintFunc local_glib_print_func
;
647 g_return_if_fail (format
!= NULL
);
649 va_start (args
, format
);
650 string
= g_strdup_vprintf (format
, args
);
653 g_mutex_lock (g_messages_lock
);
654 local_glib_print_func
= glib_print_func
;
655 g_mutex_unlock (g_messages_lock
);
657 if (local_glib_print_func
)
658 local_glib_print_func (string
);
661 ensure_stdout_valid ();
662 fputs (string
, stdout
);
669 g_set_printerr_handler (GPrintFunc func
)
671 GPrintFunc old_printerr_func
;
673 g_mutex_lock (g_messages_lock
);
674 old_printerr_func
= glib_printerr_func
;
675 glib_printerr_func
= func
;
676 g_mutex_unlock (g_messages_lock
);
678 return old_printerr_func
;
682 g_printerr (const gchar
*format
,
687 GPrintFunc local_glib_printerr_func
;
689 g_return_if_fail (format
!= NULL
);
691 va_start (args
, format
);
692 string
= g_strdup_vprintf (format
, args
);
695 g_mutex_lock (g_messages_lock
);
696 local_glib_printerr_func
= glib_printerr_func
;
697 g_mutex_unlock (g_messages_lock
);
699 if (local_glib_printerr_func
)
700 local_glib_printerr_func (string
);
703 fputs (string
, stderr
);
709 /* compatibility code */
711 g_set_error_handler (GErrorFunc func
)
713 GErrorFunc old_error_func
;
715 g_mutex_lock (g_messages_lock
);
716 old_error_func
= glib_error_func
;
717 glib_error_func
= func
;
718 g_mutex_unlock (g_messages_lock
);
720 return old_error_func
;
723 /* compatibility code */
725 g_set_warning_handler (GWarningFunc func
)
727 GWarningFunc old_warning_func
;
729 g_mutex_lock (g_messages_lock
);
730 old_warning_func
= glib_warning_func
;
731 glib_warning_func
= func
;
732 g_mutex_unlock (g_messages_lock
);
734 return old_warning_func
;
737 /* compatibility code */
739 g_set_message_handler (GPrintFunc func
)
741 GPrintFunc old_message_func
;
743 g_mutex_lock (g_messages_lock
);
744 old_message_func
= glib_message_func
;
745 glib_message_func
= func
;
746 g_mutex_unlock (g_messages_lock
);
748 return old_message_func
;
752 g_messages_init (void)
754 g_messages_lock
= g_mutex_new();
755 g_log_depth
= g_private_new(NULL
);