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.
26 /* --- structures --- */
27 typedef struct _GLogDomain GLogDomain;
28 typedef struct _GLogHandler GLogHandler;
32 GLogLevelFlags fatal_mask;
33 GLogHandler *handlers;
39 GLogLevelFlags log_level;
46 /* --- prototypes --- */
47 extern gchar* g_vsprintf (const gchar *fmt,
52 /* --- variables --- */
53 const gchar *g_log_domain_glib = "GLib";
54 static GLogDomain *g_log_domains = NULL;
55 static GLogLevelFlags g_log_always_fatal = G_LOG_FATAL_MASK;
56 static GPrintFunc glib_print_func = NULL;
57 static GPrintFunc glib_printerr_func = NULL;
58 static GErrorFunc glib_error_func = NULL;
59 static GWarningFunc glib_warning_func = NULL;
60 static GPrintFunc glib_message_func = NULL;
63 /* --- functions --- */
64 static inline GLogDomain*
65 g_log_find_domain (const gchar *log_domain)
67 register GLogDomain *domain;
69 domain = g_log_domains;
72 if (strcmp (domain->log_domain, log_domain) == 0)
74 domain = domain->next;
79 static inline GLogDomain*
80 g_log_domain_new (const gchar *log_domain)
82 register GLogDomain *domain;
84 domain = g_new (GLogDomain, 1);
85 domain->log_domain = g_strdup (log_domain);
86 domain->fatal_mask = G_LOG_FATAL_MASK;
87 domain->handlers = NULL;
88 domain->next = g_log_domains;
89 g_log_domains = domain;
95 g_log_domain_check_free (GLogDomain *domain)
97 if (domain->fatal_mask == G_LOG_FATAL_MASK &&
98 domain->handlers == NULL)
100 register GLogDomain *last, *work;
103 work = g_log_domains;
109 last->next = domain->next;
111 g_log_domains = domain->next;
112 g_free (domain->log_domain);
121 static inline GLogFunc
122 g_log_domain_get_handler (GLogDomain *domain,
123 GLogLevelFlags log_level,
126 if (domain && log_level)
128 register GLogHandler *handler;
130 handler = domain->handlers;
133 if ((handler->log_level & log_level) == log_level)
135 *data = handler->data;
136 return handler->log_func;
138 handler = handler->next;
141 return g_log_default_handler;
145 g_log_set_always_fatal (GLogLevelFlags fatal_mask)
147 GLogLevelFlags old_mask;
149 /* restrict the global mask to levels that are known to glib */
150 fatal_mask &= (1 << G_LOG_LEVEL_USER_SHIFT) - 1;
151 /* force errors to be fatal */
152 fatal_mask |= G_LOG_LEVEL_ERROR;
153 /* remove bogus flag */
154 fatal_mask &= ~G_LOG_FLAG_FATAL;
156 old_mask = g_log_always_fatal;
157 g_log_always_fatal = fatal_mask;
163 g_log_set_fatal_mask (const gchar *log_domain,
164 GLogLevelFlags fatal_mask)
166 GLogLevelFlags old_flags;
167 register GLogDomain *domain;
172 /* force errors to be fatal */
173 fatal_mask |= G_LOG_LEVEL_ERROR;
174 /* remove bogus flag */
175 fatal_mask &= ~G_LOG_FLAG_FATAL;
177 domain = g_log_find_domain (log_domain);
179 domain = g_log_domain_new (log_domain);
180 old_flags = domain->fatal_mask;
182 domain->fatal_mask = fatal_mask;
183 g_log_domain_check_free (domain);
189 g_log_set_handler (const gchar *log_domain,
190 GLogLevelFlags log_levels,
194 register GLogDomain *domain;
195 register GLogHandler *handler;
196 static guint handler_id = 0;
198 g_return_val_if_fail ((log_levels & G_LOG_LEVEL_MASK) != 0, 0);
199 g_return_val_if_fail (log_func != NULL, 0);
204 domain = g_log_find_domain (log_domain);
206 domain = g_log_domain_new (log_domain);
208 handler = g_new (GLogHandler, 1);
209 handler->id = ++handler_id;
210 handler->log_level = log_levels;
211 handler->log_func = log_func;
212 handler->data = user_data;
213 handler->next = domain->handlers;
214 domain->handlers = handler;
220 g_log_remove_handler (const gchar *log_domain,
223 register GLogDomain *domain;
225 g_return_if_fail (handler_id > 0);
230 domain = g_log_find_domain (log_domain);
233 register GLogHandler *work, *last;
236 work = domain->handlers;
239 if (work->id == handler_id)
242 last->next = work->next;
244 domain->handlers = work->next;
246 g_log_domain_check_free (domain);
252 g_warning ("g_log_remove_handler(): could not find handler with id `%d' for domain \"%s\"",
258 g_logv (const gchar *log_domain,
259 GLogLevelFlags log_level,
267 log_level &= G_LOG_LEVEL_MASK;
271 /* we use a stack buffer of fixed size, because we might get called
272 * recursively, and we can also be out of memory.
274 g_vsnprintf (buffer, 1025, format, args1, args2);
276 for (i = g_bit_nth_msf (log_level, -1); i >= 0; i = g_bit_nth_msf (log_level, i))
278 register GLogLevelFlags test_level;
281 if (log_level & test_level)
283 static guint g_log_depth = 0;
286 gpointer data = NULL;
288 domain = g_log_find_domain (log_domain ? log_domain : "");
291 test_level |= G_LOG_FLAG_RECURSION;
293 if ((((domain ? domain->fatal_mask : G_LOG_FATAL_MASK) | g_log_always_fatal) &
295 test_level |= G_LOG_FLAG_FATAL;
296 log_func = g_log_domain_get_handler (domain, test_level, &data);
297 log_func (log_domain, test_level, buffer, data);
299 /* *domain can be cluttered now */
301 if (test_level & G_LOG_FLAG_FATAL)
310 g_log (const gchar *log_domain,
311 GLogLevelFlags log_level,
315 va_list arg_list1, arg_list2;
317 va_start (arg_list1, format);
318 va_start (arg_list2, format);
319 g_logv (log_domain, log_level, format, &arg_list1, &arg_list2);
325 g_log_default_handler (const gchar *log_domain,
326 GLogLevelFlags log_level,
327 const gchar *message,
328 gpointer unused_data)
331 gboolean in_recursion;
334 in_recursion = (log_level & G_LOG_FLAG_RECURSION) != 0;
335 is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
336 log_level &= G_LOG_LEVEL_MASK;
339 message = "g_log_default_handler(): (NULL) message";
341 fd = (log_level >= G_LOG_LEVEL_MESSAGE) ? 1 : 2;
345 case G_LOG_LEVEL_ERROR:
346 if (!log_domain && glib_error_func)
348 /* compatibility code */
349 glib_error_func (message);
352 /* use write(2) for output, in case we are out of memeory */
356 write (fd, log_domain, strlen (log_domain));
360 write (fd, "\n** ", 4);
362 write (fd, "ERROR (recursed) **: ", 21);
364 write (fd, "ERROR **: ", 10);
365 write (fd, message, strlen(message));
367 write (fd, "\naborting...\n", 13);
371 case G_LOG_LEVEL_CRITICAL:
375 write (fd, log_domain, strlen (log_domain));
379 write (fd, "\n** ", 4);
381 write (fd, "CRITICAL (recursed) **: ", 24);
383 write (fd, "CRITICAL **: ", 13);
384 write (fd, message, strlen(message));
386 write (fd, "\naborting...\n", 13);
390 case G_LOG_LEVEL_WARNING:
391 if (!log_domain && glib_warning_func)
393 /* compatibility code */
394 glib_warning_func (message);
400 write (fd, log_domain, strlen (log_domain));
404 write (fd, "\n** ", 4);
406 write (fd, "WARNING (recursed) **: ", 23);
408 write (fd, "WARNING **: ", 12);
409 write (fd, message, strlen(message));
411 write (fd, "\naborting...\n", 13);
415 case G_LOG_LEVEL_MESSAGE:
416 if (!log_domain && glib_message_func)
418 /* compatibility code */
419 glib_message_func (message);
424 write (fd, log_domain, strlen (log_domain));
428 write (fd, "Message (recursed): ", 20);
430 write (fd, "Message: ", 9);
431 write (fd, message, strlen(message));
433 write (fd, "\naborting...\n", 13);
437 case G_LOG_LEVEL_INFO:
440 write (fd, log_domain, strlen (log_domain));
444 write (fd, "INFO (recursed): ", 17);
446 write (fd, "INFO: ", 6);
447 write (fd, message, strlen(message));
449 write (fd, "\naborting...\n", 13);
453 case G_LOG_LEVEL_DEBUG:
456 write (fd, log_domain, strlen (log_domain));
460 write (fd, "DEBUG (recursed): ", 18);
462 write (fd, "DEBUG: ", 7);
463 write (fd, message, strlen(message));
465 write (fd, "\naborting...\n", 13);
470 /* we are used for a log level that is not defined by GLib itself,
471 * try to make the best out of it.
475 write (fd, log_domain, strlen (log_domain));
477 write (fd, "-LOG (recursed:", 15);
479 write (fd, "-LOG (", 6);
481 else if (in_recursion)
482 write (fd, "LOG (recursed:", 14);
484 write (fd, "LOG (", 5);
487 gchar string[] = "0x00): ";
488 gchar *p = string + 2;
491 i = g_bit_nth_msf (log_level, -1);
494 *p = '0' + (i & 0xf);
498 write (fd, string, 7);
501 write (fd, "): ", 3);
502 write (fd, message, strlen(message));
504 write (fd, "\naborting...\n", 13);
512 g_set_print_handler (GPrintFunc func)
514 GPrintFunc old_print_func;
516 old_print_func = glib_print_func;
517 glib_print_func = func;
519 return old_print_func;
523 g_print (const gchar *format,
529 g_return_if_fail (format != NULL);
531 va_start (args, format);
532 va_start (args2, format);
533 buf = g_vsprintf (format, &args, &args2);
541 string = g_strdup (buf);
542 glib_print_func (string);
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 va_start (args2, format);
574 buf = g_vsprintf (format, &args, &args2);
578 if (glib_printerr_func)
582 string = g_strdup (buf);
583 glib_printerr_func (string);
593 /* compatibility code */
595 g_set_error_handler (GErrorFunc func)
597 GErrorFunc old_error_func;
599 old_error_func = glib_error_func;
600 glib_error_func = func;
602 return old_error_func;
605 /* compatibility code */
607 g_set_warning_handler (GWarningFunc func)
609 GWarningFunc old_warning_func;
611 old_warning_func = glib_warning_func;
612 glib_warning_func = func;
614 return old_warning_func;
617 /* compatibility code */
619 g_set_message_handler (GPrintFunc func)
621 GPrintFunc old_message_func;
623 old_message_func = glib_message_func;
624 glib_message_func = func;
626 return old_message_func;