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.
27 /* --- structures --- */
28 typedef struct _GLogDomain GLogDomain;
29 typedef struct _GLogHandler GLogHandler;
33 GLogLevelFlags fatal_mask;
34 GLogHandler *handlers;
40 GLogLevelFlags log_level;
47 /* --- variables --- */
48 const gchar *g_log_domain_glib = "GLib";
49 static GLogDomain *g_log_domains = NULL;
50 static GLogLevelFlags g_log_always_fatal = G_LOG_FATAL_MASK;
51 static GPrintFunc glib_print_func = NULL;
52 static GPrintFunc glib_printerr_func = NULL;
53 static GErrorFunc glib_error_func = NULL;
54 static GWarningFunc glib_warning_func = NULL;
55 static GPrintFunc glib_message_func = NULL;
58 /* --- functions --- */
59 static inline GLogDomain*
60 g_log_find_domain (const gchar *log_domain)
62 register GLogDomain *domain;
64 domain = g_log_domains;
67 if (strcmp (domain->log_domain, log_domain) == 0)
69 domain = domain->next;
74 static inline GLogDomain*
75 g_log_domain_new (const gchar *log_domain)
77 register GLogDomain *domain;
79 domain = g_new (GLogDomain, 1);
80 domain->log_domain = g_strdup (log_domain);
81 domain->fatal_mask = G_LOG_FATAL_MASK;
82 domain->handlers = NULL;
83 domain->next = g_log_domains;
84 g_log_domains = domain;
90 g_log_domain_check_free (GLogDomain *domain)
92 if (domain->fatal_mask == G_LOG_FATAL_MASK &&
93 domain->handlers == NULL)
95 register GLogDomain *last, *work;
104 last->next = domain->next;
106 g_log_domains = domain->next;
107 g_free (domain->log_domain);
116 static inline GLogFunc
117 g_log_domain_get_handler (GLogDomain *domain,
118 GLogLevelFlags log_level,
121 if (domain && log_level)
123 register GLogHandler *handler;
125 handler = domain->handlers;
128 if ((handler->log_level & log_level) == log_level)
130 *data = handler->data;
131 return handler->log_func;
133 handler = handler->next;
136 return g_log_default_handler;
140 g_log_set_always_fatal (GLogLevelFlags fatal_mask)
142 GLogLevelFlags old_mask;
144 /* restrict the global mask to levels that are known to glib */
145 fatal_mask &= (1 << G_LOG_LEVEL_USER_SHIFT) - 1;
146 /* force errors to be fatal */
147 fatal_mask |= G_LOG_LEVEL_ERROR;
148 /* remove bogus flag */
149 fatal_mask &= ~G_LOG_FLAG_FATAL;
151 old_mask = g_log_always_fatal;
152 g_log_always_fatal = fatal_mask;
158 g_log_set_fatal_mask (const gchar *log_domain,
159 GLogLevelFlags fatal_mask)
161 GLogLevelFlags old_flags;
162 register GLogDomain *domain;
167 /* force errors to be fatal */
168 fatal_mask |= G_LOG_LEVEL_ERROR;
169 /* remove bogus flag */
170 fatal_mask &= ~G_LOG_FLAG_FATAL;
172 domain = g_log_find_domain (log_domain);
174 domain = g_log_domain_new (log_domain);
175 old_flags = domain->fatal_mask;
177 domain->fatal_mask = fatal_mask;
178 g_log_domain_check_free (domain);
184 g_log_set_handler (const gchar *log_domain,
185 GLogLevelFlags log_levels,
189 register GLogDomain *domain;
190 register GLogHandler *handler;
191 static guint handler_id = 0;
193 g_return_val_if_fail ((log_levels & G_LOG_LEVEL_MASK) != 0, 0);
194 g_return_val_if_fail (log_func != NULL, 0);
199 domain = g_log_find_domain (log_domain);
201 domain = g_log_domain_new (log_domain);
203 handler = g_new (GLogHandler, 1);
204 handler->id = ++handler_id;
205 handler->log_level = log_levels;
206 handler->log_func = log_func;
207 handler->data = user_data;
208 handler->next = domain->handlers;
209 domain->handlers = handler;
215 g_log_remove_handler (const gchar *log_domain,
218 register GLogDomain *domain;
220 g_return_if_fail (handler_id > 0);
225 domain = g_log_find_domain (log_domain);
228 register GLogHandler *work, *last;
231 work = domain->handlers;
234 if (work->id == handler_id)
237 last->next = work->next;
239 domain->handlers = work->next;
241 g_log_domain_check_free (domain);
247 g_warning ("g_log_remove_handler(): could not find handler with id `%d' for domain \"%s\"",
253 g_logv (const gchar *log_domain,
254 GLogLevelFlags log_level,
262 log_level &= G_LOG_LEVEL_MASK;
266 /* we use a stack buffer of fixed size, because we might get called
269 G_VA_COPY (args2, args1);
270 if (g_printf_string_upper_bound (format, args1) < 1024)
271 vsprintf (buffer, format, args2);
274 /* since we might be out of memory, we can't use g_vsnprintf(). */
275 #ifdef HAVE_VSNPRINTF
276 vsnprintf (buffer, 1024, format, args2);
277 #else /* !HAVE_VSNPRINTF */
278 /* we are out of luck here */
279 strncpy (buffer, format, 1024);
280 #endif /* !HAVE_VSNPRINTF */
285 for (i = g_bit_nth_msf (log_level, -1); i >= 0; i = g_bit_nth_msf (log_level, i))
287 register GLogLevelFlags test_level;
290 if (log_level & test_level)
292 static guint g_log_depth = 0;
295 gpointer data = NULL;
297 domain = g_log_find_domain (log_domain ? log_domain : "");
300 test_level |= G_LOG_FLAG_RECURSION;
302 if ((((domain ? domain->fatal_mask : G_LOG_FATAL_MASK) | g_log_always_fatal) &
304 test_level |= G_LOG_FLAG_FATAL;
305 log_func = g_log_domain_get_handler (domain, test_level, &data);
306 log_func (log_domain, test_level, buffer, data);
308 /* *domain can be cluttered now */
310 if (test_level & G_LOG_FLAG_FATAL)
319 g_log (const gchar *log_domain,
320 GLogLevelFlags log_level,
326 va_start (args, format);
327 g_logv (log_domain, log_level, format, args);
332 g_log_default_handler (const gchar *log_domain,
333 GLogLevelFlags log_level,
334 const gchar *message,
335 gpointer unused_data)
338 gboolean in_recursion;
341 in_recursion = (log_level & G_LOG_FLAG_RECURSION) != 0;
342 is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
343 log_level &= G_LOG_LEVEL_MASK;
346 message = "g_log_default_handler(): (NULL) message";
348 fd = (log_level >= G_LOG_LEVEL_MESSAGE) ? 1 : 2;
352 case G_LOG_LEVEL_ERROR:
353 if (!log_domain && glib_error_func)
355 /* compatibility code */
356 glib_error_func (message);
359 /* use write(2) for output, in case we are out of memeory */
363 write (fd, log_domain, strlen (log_domain));
367 write (fd, "\n** ", 4);
369 write (fd, "ERROR (recursed) **: ", 21);
371 write (fd, "ERROR **: ", 10);
372 write (fd, message, strlen(message));
374 write (fd, "\naborting...\n", 13);
378 case G_LOG_LEVEL_CRITICAL:
382 write (fd, log_domain, strlen (log_domain));
386 write (fd, "\n** ", 4);
388 write (fd, "CRITICAL (recursed) **: ", 24);
390 write (fd, "CRITICAL **: ", 13);
391 write (fd, message, strlen(message));
393 write (fd, "\naborting...\n", 13);
397 case G_LOG_LEVEL_WARNING:
398 if (!log_domain && glib_warning_func)
400 /* compatibility code */
401 glib_warning_func (message);
407 write (fd, log_domain, strlen (log_domain));
411 write (fd, "\n** ", 4);
413 write (fd, "WARNING (recursed) **: ", 23);
415 write (fd, "WARNING **: ", 12);
416 write (fd, message, strlen(message));
418 write (fd, "\naborting...\n", 13);
422 case G_LOG_LEVEL_MESSAGE:
423 if (!log_domain && glib_message_func)
425 /* compatibility code */
426 glib_message_func (message);
431 write (fd, log_domain, strlen (log_domain));
435 write (fd, "Message (recursed): ", 20);
437 write (fd, "Message: ", 9);
438 write (fd, message, strlen(message));
440 write (fd, "\naborting...\n", 13);
444 case G_LOG_LEVEL_INFO:
447 write (fd, log_domain, strlen (log_domain));
451 write (fd, "INFO (recursed): ", 17);
453 write (fd, "INFO: ", 6);
454 write (fd, message, strlen(message));
456 write (fd, "\naborting...\n", 13);
460 case G_LOG_LEVEL_DEBUG:
463 write (fd, log_domain, strlen (log_domain));
467 write (fd, "DEBUG (recursed): ", 18);
469 write (fd, "DEBUG: ", 7);
470 write (fd, message, strlen(message));
472 write (fd, "\naborting...\n", 13);
477 /* we are used for a log level that is not defined by GLib itself,
478 * try to make the best out of it.
482 write (fd, log_domain, strlen (log_domain));
484 write (fd, "-LOG (recursed:", 15);
486 write (fd, "-LOG (", 6);
488 else if (in_recursion)
489 write (fd, "LOG (recursed:", 14);
491 write (fd, "LOG (", 5);
494 gchar string[] = "0x00): ";
495 gchar *p = string + 2;
498 i = g_bit_nth_msf (log_level, -1);
501 *p = '0' + (i & 0xf);
505 write (fd, string, 7);
508 write (fd, "): ", 3);
509 write (fd, message, strlen(message));
511 write (fd, "\naborting...\n", 13);
519 g_set_print_handler (GPrintFunc func)
521 GPrintFunc old_print_func;
523 old_print_func = glib_print_func;
524 glib_print_func = func;
526 return old_print_func;
530 g_print (const gchar *format,
536 g_return_if_fail (format != NULL);
538 va_start (args, format);
539 string = g_strdup_vprintf (format, args);
543 glib_print_func (string);
546 fputs (string, stdout);
553 g_set_printerr_handler (GPrintFunc func)
555 GPrintFunc old_printerr_func;
557 old_printerr_func = glib_printerr_func;
558 glib_printerr_func = func;
560 return old_printerr_func;
564 g_printerr (const gchar *format,
570 g_return_if_fail (format != NULL);
572 va_start (args, format);
573 string = g_strdup_vprintf (format, args);
576 if (glib_printerr_func)
577 glib_printerr_func (string);
580 fputs (string, stderr);
586 /* compatibility code */
588 g_set_error_handler (GErrorFunc func)
590 GErrorFunc old_error_func;
592 old_error_func = glib_error_func;
593 glib_error_func = func;
595 return old_error_func;
598 /* compatibility code */
600 g_set_warning_handler (GWarningFunc func)
602 GWarningFunc old_warning_func;
604 old_warning_func = glib_warning_func;
605 glib_warning_func = func;
607 return old_warning_func;
610 /* compatibility code */
612 g_set_message_handler (GPrintFunc func)
614 GPrintFunc old_message_func;
616 old_message_func = glib_message_func;
617 glib_message_func = func;
619 return old_message_func;