Home | History | Annotate | Download | only in glib
      1 /* GLIB - Library of useful routines for C programming
      2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
      3  *
      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.
      8  *
      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.
     13  *
     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.
     18  */
     19 
     20 /*
     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/.
     25  */
     26 
     27 /*
     28  * MT safe
     29  */
     30 
     31 #include "config.h"
     32 
     33 #include <stdlib.h>
     34 #include <stdarg.h>
     35 #include <stdio.h>
     36 #include <string.h>
     37 #ifdef HAVE_UNISTD_H
     38 #include <unistd.h>
     39 #endif
     40 #include <signal.h>
     41 #include <locale.h>
     42 #include <errno.h>
     43 
     44 #include "glib.h"
     45 #include "gdebug.h"
     46 #include "gprintfint.h"
     47 #include "gthreadprivate.h"
     48 #include "galias.h"
     49 
     50 #ifdef G_OS_WIN32
     51 #include <process.h>		/* For getpid() */
     52 #include <io.h>
     53 #  define STRICT		/* Strict typing, please */
     54 #  define _WIN32_WINDOWS 0x0401 /* to get IsDebuggerPresent */
     55 #  include <windows.h>
     56 #  undef STRICT
     57 #endif
     58 
     59 /* --- structures --- */
     60 typedef struct _GLogDomain	GLogDomain;
     61 typedef struct _GLogHandler	GLogHandler;
     62 struct _GLogDomain
     63 {
     64   gchar		*log_domain;
     65   GLogLevelFlags fatal_mask;
     66   GLogHandler	*handlers;
     67   GLogDomain	*next;
     68 };
     69 struct _GLogHandler
     70 {
     71   guint		 id;
     72   GLogLevelFlags log_level;
     73   GLogFunc	 log_func;
     74   gpointer	 data;
     75   GLogHandler	*next;
     76 };
     77 
     78 
     79 /* --- variables --- */
     80 static GMutex        *g_messages_lock = NULL;
     81 static GLogDomain    *g_log_domains = NULL;
     82 static GLogLevelFlags g_log_always_fatal = G_LOG_FATAL_MASK;
     83 static GPrintFunc     glib_print_func = NULL;
     84 static GPrintFunc     glib_printerr_func = NULL;
     85 static GPrivate	     *g_log_depth = NULL;
     86 static GLogLevelFlags g_log_msg_prefix = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_DEBUG;
     87 static GLogFunc       default_log_func = g_log_default_handler;
     88 static gpointer       default_log_data = NULL;
     89 
     90 /* --- functions --- */
     91 #ifdef G_OS_WIN32
     92 #  define STRICT
     93 #  include <windows.h>
     94 #  undef STRICT
     95 static gboolean win32_keep_fatal_message = FALSE;
     96 
     97 /* This default message will usually be overwritten. */
     98 /* Yes, a fixed size buffer is bad. So sue me. But g_error() is never
     99  * called with huge strings, is it?
    100  */
    101 static gchar  fatal_msg_buf[1000] = "Unspecified fatal error encountered, aborting.";
    102 static gchar *fatal_msg_ptr = fatal_msg_buf;
    103 
    104 #undef write
    105 static inline int
    106 dowrite (int          fd,
    107 	 const void  *buf,
    108 	 unsigned int len)
    109 {
    110   if (win32_keep_fatal_message)
    111     {
    112       memcpy (fatal_msg_ptr, buf, len);
    113       fatal_msg_ptr += len;
    114       *fatal_msg_ptr = 0;
    115       return len;
    116     }
    117 
    118   write (fd, buf, len);
    119 
    120   return len;
    121 }
    122 #define write(fd, buf, len) dowrite(fd, buf, len)
    123 
    124 #endif
    125 
    126 static void
    127 write_string (int          fd,
    128 	      const gchar *string)
    129 {
    130   write (fd, string, strlen (string));
    131 }
    132 
    133 static void
    134 g_messages_prefixed_init (void)
    135 {
    136   static gboolean initialized = FALSE;
    137 
    138   if (!initialized)
    139     {
    140       const gchar *val;
    141 
    142       initialized = TRUE;
    143       val = g_getenv ("G_MESSAGES_PREFIXED");
    144 
    145       if (val)
    146 	{
    147 	  const GDebugKey keys[] = {
    148 	    { "error", G_LOG_LEVEL_ERROR },
    149 	    { "critical", G_LOG_LEVEL_CRITICAL },
    150 	    { "warning", G_LOG_LEVEL_WARNING },
    151 	    { "message", G_LOG_LEVEL_MESSAGE },
    152 	    { "info", G_LOG_LEVEL_INFO },
    153 	    { "debug", G_LOG_LEVEL_DEBUG }
    154 	  };
    155 
    156 	  g_log_msg_prefix = g_parse_debug_string (val, keys, G_N_ELEMENTS (keys));
    157 	}
    158     }
    159 }
    160 
    161 static GLogDomain*
    162 g_log_find_domain_L (const gchar *log_domain)
    163 {
    164   register GLogDomain *domain;
    165 
    166   domain = g_log_domains;
    167   while (domain)
    168     {
    169       if (strcmp (domain->log_domain, log_domain) == 0)
    170 	return domain;
    171       domain = domain->next;
    172     }
    173   return NULL;
    174 }
    175 
    176 static GLogDomain*
    177 g_log_domain_new_L (const gchar *log_domain)
    178 {
    179   register GLogDomain *domain;
    180 
    181   domain = g_new (GLogDomain, 1);
    182   domain->log_domain = g_strdup (log_domain);
    183   domain->fatal_mask = G_LOG_FATAL_MASK;
    184   domain->handlers = NULL;
    185 
    186   domain->next = g_log_domains;
    187   g_log_domains = domain;
    188 
    189   return domain;
    190 }
    191 
    192 static void
    193 g_log_domain_check_free_L (GLogDomain *domain)
    194 {
    195   if (domain->fatal_mask == G_LOG_FATAL_MASK &&
    196       domain->handlers == NULL)
    197     {
    198       register GLogDomain *last, *work;
    199 
    200       last = NULL;
    201 
    202       work = g_log_domains;
    203       while (work)
    204 	{
    205 	  if (work == domain)
    206 	    {
    207 	      if (last)
    208 		last->next = domain->next;
    209 	      else
    210 		g_log_domains = domain->next;
    211 	      g_free (domain->log_domain);
    212 	      g_free (domain);
    213 	      break;
    214 	    }
    215 	  last = work;
    216 	  work = last->next;
    217 	}
    218     }
    219 }
    220 
    221 static GLogFunc
    222 g_log_domain_get_handler_L (GLogDomain	*domain,
    223 			    GLogLevelFlags log_level,
    224 			    gpointer	*data)
    225 {
    226   if (domain && log_level)
    227     {
    228       register GLogHandler *handler;
    229 
    230       handler = domain->handlers;
    231       while (handler)
    232 	{
    233 	  if ((handler->log_level & log_level) == log_level)
    234 	    {
    235 	      *data = handler->data;
    236 	      return handler->log_func;
    237 	    }
    238 	  handler = handler->next;
    239 	}
    240     }
    241 
    242   *data = default_log_data;
    243   return default_log_func;
    244 }
    245 
    246 GLogLevelFlags
    247 g_log_set_always_fatal (GLogLevelFlags fatal_mask)
    248 {
    249   GLogLevelFlags old_mask;
    250 
    251   /* restrict the global mask to levels that are known to glib
    252    * since this setting applies to all domains
    253    */
    254   fatal_mask &= (1 << G_LOG_LEVEL_USER_SHIFT) - 1;
    255   /* force errors to be fatal */
    256   fatal_mask |= G_LOG_LEVEL_ERROR;
    257   /* remove bogus flag */
    258   fatal_mask &= ~G_LOG_FLAG_FATAL;
    259 
    260   g_mutex_lock (g_messages_lock);
    261   old_mask = g_log_always_fatal;
    262   g_log_always_fatal = fatal_mask;
    263   g_mutex_unlock (g_messages_lock);
    264 
    265   return old_mask;
    266 }
    267 
    268 GLogLevelFlags
    269 g_log_set_fatal_mask (const gchar   *log_domain,
    270 		      GLogLevelFlags fatal_mask)
    271 {
    272   GLogLevelFlags old_flags;
    273   register GLogDomain *domain;
    274 
    275   if (!log_domain)
    276     log_domain = "";
    277 
    278   /* force errors to be fatal */
    279   fatal_mask |= G_LOG_LEVEL_ERROR;
    280   /* remove bogus flag */
    281   fatal_mask &= ~G_LOG_FLAG_FATAL;
    282 
    283   g_mutex_lock (g_messages_lock);
    284 
    285   domain = g_log_find_domain_L (log_domain);
    286   if (!domain)
    287     domain = g_log_domain_new_L (log_domain);
    288   old_flags = domain->fatal_mask;
    289 
    290   domain->fatal_mask = fatal_mask;
    291   g_log_domain_check_free_L (domain);
    292 
    293   g_mutex_unlock (g_messages_lock);
    294 
    295   return old_flags;
    296 }
    297 
    298 guint
    299 g_log_set_handler (const gchar	 *log_domain,
    300 		   GLogLevelFlags log_levels,
    301 		   GLogFunc	  log_func,
    302 		   gpointer	  user_data)
    303 {
    304   static guint handler_id = 0;
    305   GLogDomain *domain;
    306   GLogHandler *handler;
    307 
    308   g_return_val_if_fail ((log_levels & G_LOG_LEVEL_MASK) != 0, 0);
    309   g_return_val_if_fail (log_func != NULL, 0);
    310 
    311   if (!log_domain)
    312     log_domain = "";
    313 
    314   handler = g_new (GLogHandler, 1);
    315 
    316   g_mutex_lock (g_messages_lock);
    317 
    318   domain = g_log_find_domain_L (log_domain);
    319   if (!domain)
    320     domain = g_log_domain_new_L (log_domain);
    321 
    322   handler->id = ++handler_id;
    323   handler->log_level = log_levels;
    324   handler->log_func = log_func;
    325   handler->data = user_data;
    326   handler->next = domain->handlers;
    327   domain->handlers = handler;
    328 
    329   g_mutex_unlock (g_messages_lock);
    330 
    331   return handler_id;
    332 }
    333 
    334 GLogFunc
    335 g_log_set_default_handler (GLogFunc log_func,
    336 			   gpointer user_data)
    337 {
    338   GLogFunc old_log_func;
    339 
    340   g_mutex_lock (g_messages_lock);
    341   old_log_func = default_log_func;
    342   default_log_func = log_func;
    343   default_log_data = user_data;
    344   g_mutex_unlock (g_messages_lock);
    345 
    346   return old_log_func;
    347 }
    348 
    349 void
    350 g_log_remove_handler (const gchar *log_domain,
    351 		      guint	   handler_id)
    352 {
    353   register GLogDomain *domain;
    354 
    355   g_return_if_fail (handler_id > 0);
    356 
    357   if (!log_domain)
    358     log_domain = "";
    359 
    360   g_mutex_lock (g_messages_lock);
    361   domain = g_log_find_domain_L (log_domain);
    362   if (domain)
    363     {
    364       GLogHandler *work, *last;
    365 
    366       last = NULL;
    367       work = domain->handlers;
    368       while (work)
    369 	{
    370 	  if (work->id == handler_id)
    371 	    {
    372 	      if (last)
    373 		last->next = work->next;
    374 	      else
    375 		domain->handlers = work->next;
    376 	      g_log_domain_check_free_L (domain);
    377 	      g_mutex_unlock (g_messages_lock);
    378 	      g_free (work);
    379 	      return;
    380 	    }
    381 	  last = work;
    382 	  work = last->next;
    383 	}
    384     }
    385   g_mutex_unlock (g_messages_lock);
    386   g_warning ("%s: could not find handler with id `%d' for domain \"%s\"",
    387 	     G_STRLOC, handler_id, log_domain);
    388 }
    389 
    390 void
    391 g_logv (const gchar   *log_domain,
    392 	GLogLevelFlags log_level,
    393 	const gchar   *format,
    394 	va_list	       args1)
    395 {
    396   gboolean was_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
    397   gboolean was_recursion = (log_level & G_LOG_FLAG_RECURSION) != 0;
    398   gint i;
    399 
    400   log_level &= G_LOG_LEVEL_MASK;
    401   if (!log_level)
    402     return;
    403 
    404   for (i = g_bit_nth_msf (log_level, -1); i >= 0; i = g_bit_nth_msf (log_level, i))
    405     {
    406       register GLogLevelFlags test_level;
    407 
    408       test_level = 1 << i;
    409       if (log_level & test_level)
    410 	{
    411 	  guint depth = GPOINTER_TO_UINT (g_private_get (g_log_depth));
    412 	  GLogDomain *domain;
    413 	  GLogFunc log_func;
    414 	  GLogLevelFlags domain_fatal_mask;
    415 	  gpointer data = NULL;
    416 
    417 	  if (was_fatal)
    418 	    test_level |= G_LOG_FLAG_FATAL;
    419 	  if (was_recursion)
    420 	    test_level |= G_LOG_FLAG_RECURSION;
    421 
    422 	  /* check recursion and lookup handler */
    423 	  g_mutex_lock (g_messages_lock);
    424 	  domain = g_log_find_domain_L (log_domain ? log_domain : "");
    425 	  if (depth)
    426 	    test_level |= G_LOG_FLAG_RECURSION;
    427 	  depth++;
    428 	  domain_fatal_mask = domain ? domain->fatal_mask : G_LOG_FATAL_MASK;
    429 	  if ((domain_fatal_mask | g_log_always_fatal) & test_level)
    430 	    test_level |= G_LOG_FLAG_FATAL;
    431 	  if (test_level & G_LOG_FLAG_RECURSION)
    432 	    log_func = _g_log_fallback_handler;
    433 	  else
    434 	    log_func = g_log_domain_get_handler_L (domain, test_level, &data);
    435 	  domain = NULL;
    436 	  g_mutex_unlock (g_messages_lock);
    437 
    438 	  g_private_set (g_log_depth, GUINT_TO_POINTER (depth));
    439 
    440 	  /* had to defer debug initialization until we can keep track of recursion */
    441 	  if (!(test_level & G_LOG_FLAG_RECURSION) && !_g_debug_initialized)
    442 	    {
    443 	      GLogLevelFlags orig_test_level = test_level;
    444 
    445 	      _g_debug_init ();
    446 	      if ((domain_fatal_mask | g_log_always_fatal) & test_level)
    447 		test_level |= G_LOG_FLAG_FATAL;
    448 	      if (test_level != orig_test_level)
    449 		{
    450 		  /* need a relookup, not nice, but not too bad either */
    451 		  g_mutex_lock (g_messages_lock);
    452 		  domain = g_log_find_domain_L (log_domain ? log_domain : "");
    453 		  log_func = g_log_domain_get_handler_L (domain, test_level, &data);
    454 		  domain = NULL;
    455 		  g_mutex_unlock (g_messages_lock);
    456 		}
    457 	    }
    458 
    459 	  if (test_level & G_LOG_FLAG_RECURSION)
    460 	    {
    461 	      /* we use a stack buffer of fixed size, since we're likely
    462 	       * in an out-of-memory situation
    463 	       */
    464 	      gchar buffer[1025];
    465               gsize size;
    466               va_list args2;
    467 
    468               G_VA_COPY (args2, args1);
    469 	      size = _g_vsnprintf (buffer, 1024, format, args2);
    470               va_end (args2);
    471 
    472 	      log_func (log_domain, test_level, buffer, data);
    473 	    }
    474 	  else
    475 	    {
    476 	      gchar *msg;
    477               va_list args2;
    478 
    479               G_VA_COPY (args2, args1);
    480               msg = g_strdup_vprintf (format, args2);
    481               va_end (args2);
    482 
    483 	      log_func (log_domain, test_level, msg, data);
    484 
    485 	      g_free (msg);
    486 	    }
    487 
    488 	  if (test_level & G_LOG_FLAG_FATAL)
    489 	    {
    490 #ifdef G_OS_WIN32
    491 	      gchar *locale_msg = g_locale_from_utf8 (fatal_msg_buf, -1, NULL, NULL, NULL);
    492 
    493 	      MessageBox (NULL, locale_msg, NULL,
    494 			  MB_ICONERROR|MB_SETFOREGROUND);
    495 	      if (IsDebuggerPresent () && !(test_level & G_LOG_FLAG_RECURSION))
    496 		G_BREAKPOINT ();
    497 	      else
    498 		abort ();
    499 #else
    500 #if defined (G_ENABLE_DEBUG) && defined (SIGTRAP)
    501 	      if (!(test_level & G_LOG_FLAG_RECURSION))
    502 		G_BREAKPOINT ();
    503 	      else
    504 		abort ();
    505 #else /* !G_ENABLE_DEBUG || !SIGTRAP */
    506 	      abort ();
    507 #endif /* !G_ENABLE_DEBUG || !SIGTRAP */
    508 #endif /* !G_OS_WIN32 */
    509 	    }
    510 
    511 	  depth--;
    512 	  g_private_set (g_log_depth, GUINT_TO_POINTER (depth));
    513 	}
    514     }
    515 }
    516 
    517 void
    518 g_log (const gchar   *log_domain,
    519        GLogLevelFlags log_level,
    520        const gchar   *format,
    521        ...)
    522 {
    523   va_list args;
    524 
    525   va_start (args, format);
    526   g_logv (log_domain, log_level, format, args);
    527   va_end (args);
    528 }
    529 
    530 void
    531 g_return_if_fail_warning (const char *log_domain,
    532 			  const char *pretty_function,
    533 			  const char *expression)
    534 {
    535   /*
    536    * Omit the prefix used by the PLT-reduction
    537    * technique used in GTK+.
    538    */
    539   if (g_str_has_prefix (pretty_function, "IA__"))
    540     pretty_function += 4;
    541   g_log (log_domain,
    542 	 G_LOG_LEVEL_CRITICAL,
    543 	 "%s: assertion `%s' failed",
    544 	 pretty_function,
    545 	 expression);
    546 }
    547 
    548 void
    549 g_warn_message (const char     *domain,
    550                 const char     *file,
    551                 int             line,
    552                 const char     *func,
    553                 const char     *warnexpr)
    554 {
    555   char *s, lstr[32];
    556   g_snprintf (lstr, 32, "%d", line);
    557   if (warnexpr)
    558     s = g_strconcat ("(", file, ":", lstr, "):",
    559                      func, func[0] ? ":" : "",
    560                      " runtime check failed: (", warnexpr, ")", NULL);
    561   else
    562     s = g_strconcat ("(", file, ":", lstr, "):",
    563                      func, func[0] ? ":" : "",
    564                      " ", "code should not be reached", NULL);
    565   g_log (domain, G_LOG_LEVEL_WARNING, "%s", s);
    566   g_free (s);
    567 }
    568 
    569 void
    570 g_assert_warning (const char *log_domain,
    571 		  const char *file,
    572 		  const int   line,
    573 		  const char *pretty_function,
    574 		  const char *expression)
    575 {
    576   /*
    577    * Omit the prefix used by the PLT-reduction
    578    * technique used in GTK+.
    579    */
    580   if (g_str_has_prefix (pretty_function, "IA__"))
    581     pretty_function += 4;
    582   g_log (log_domain,
    583 	 G_LOG_LEVEL_ERROR,
    584 	 expression
    585 	 ? "file %s: line %d (%s): assertion failed: (%s)"
    586 	 : "file %s: line %d (%s): should not be reached",
    587 	 file,
    588 	 line,
    589 	 pretty_function,
    590 	 expression);
    591   abort ();
    592 }
    593 
    594 #define CHAR_IS_SAFE(wc) (!((wc < 0x20 && wc != '\t' && wc != '\n' && wc != '\r') || \
    595 			    (wc == 0x7f) || \
    596 			    (wc >= 0x80 && wc < 0xa0)))
    597 
    598 static gchar*
    599 strdup_convert (const gchar *string,
    600 		const gchar *charset)
    601 {
    602   if (!g_utf8_validate (string, -1, NULL))
    603     {
    604       GString *gstring = g_string_new ("[Invalid UTF-8] ");
    605       guchar *p;
    606 
    607       for (p = (guchar *)string; *p; p++)
    608 	{
    609 	  if (CHAR_IS_SAFE(*p) &&
    610 	      !(*p == '\r' && *(p + 1) != '\n') &&
    611 	      *p < 0x80)
    612 	    g_string_append_c (gstring, *p);
    613 	  else
    614 	    g_string_append_printf (gstring, "\\x%02x", (guint)(guchar)*p);
    615 	}
    616 
    617       return g_string_free (gstring, FALSE);
    618     }
    619   else
    620     {
    621       GError *err = NULL;
    622 
    623       gchar *result = g_convert_with_fallback (string, -1, charset, "UTF-8", "?", NULL, NULL, &err);
    624       if (result)
    625 	return result;
    626       else
    627 	{
    628 	  /* Not thread-safe, but doesn't matter if we print the warning twice
    629 	   */
    630 	  static gboolean warned = FALSE;
    631 	  if (!warned)
    632 	    {
    633 	      warned = TRUE;
    634 	      _g_fprintf (stderr, "GLib: Cannot convert message: %s\n", err->message);
    635 	    }
    636 	  g_error_free (err);
    637 
    638 	  return g_strdup (string);
    639 	}
    640     }
    641 }
    642 
    643 /* For a radix of 8 we need at most 3 output bytes for 1 input
    644  * byte. Additionally we might need up to 2 output bytes for the
    645  * readix prefix and 1 byte for the trailing NULL.
    646  */
    647 #define FORMAT_UNSIGNED_BUFSIZE ((GLIB_SIZEOF_LONG * 3) + 3)
    648 
    649 static void
    650 format_unsigned (gchar  *buf,
    651 		 gulong  num,
    652 		 guint   radix)
    653 {
    654   gulong tmp;
    655   gchar c;
    656   gint i, n;
    657 
    658   /* we may not call _any_ GLib functions here (or macros like g_return_if_fail()) */
    659 
    660   if (radix != 8 && radix != 10 && radix != 16)
    661     {
    662       *buf = '\000';
    663       return;
    664     }
    665 
    666   if (!num)
    667     {
    668       *buf++ = '0';
    669       *buf = '\000';
    670       return;
    671     }
    672 
    673   if (radix == 16)
    674     {
    675       *buf++ = '0';
    676       *buf++ = 'x';
    677     }
    678   else if (radix == 8)
    679     {
    680       *buf++ = '0';
    681     }
    682 
    683   n = 0;
    684   tmp = num;
    685   while (tmp)
    686     {
    687       tmp /= radix;
    688       n++;
    689     }
    690 
    691   i = n;
    692 
    693   /* Again we can't use g_assert; actually this check should _never_ fail. */
    694   if (n > FORMAT_UNSIGNED_BUFSIZE - 3)
    695     {
    696       *buf = '\000';
    697       return;
    698     }
    699 
    700   while (num)
    701     {
    702       i--;
    703       c = (num % radix);
    704       if (c < 10)
    705 	buf[i] = c + '0';
    706       else
    707 	buf[i] = c + 'a' - 10;
    708       num /= radix;
    709     }
    710 
    711   buf[n] = '\000';
    712 }
    713 
    714 /* string size big enough to hold level prefix */
    715 #define	STRING_BUFFER_SIZE	(FORMAT_UNSIGNED_BUFSIZE + 32)
    716 
    717 #define	ALERT_LEVELS		(G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING)
    718 
    719 static int
    720 mklevel_prefix (gchar          level_prefix[STRING_BUFFER_SIZE],
    721 		GLogLevelFlags log_level)
    722 {
    723   gboolean to_stdout = TRUE;
    724 
    725   /* we may not call _any_ GLib functions here */
    726 
    727   switch (log_level & G_LOG_LEVEL_MASK)
    728     {
    729     case G_LOG_LEVEL_ERROR:
    730       strcpy (level_prefix, "ERROR");
    731       to_stdout = FALSE;
    732       break;
    733     case G_LOG_LEVEL_CRITICAL:
    734       strcpy (level_prefix, "CRITICAL");
    735       to_stdout = FALSE;
    736       break;
    737     case G_LOG_LEVEL_WARNING:
    738       strcpy (level_prefix, "WARNING");
    739       to_stdout = FALSE;
    740       break;
    741     case G_LOG_LEVEL_MESSAGE:
    742       strcpy (level_prefix, "Message");
    743       to_stdout = FALSE;
    744       break;
    745     case G_LOG_LEVEL_INFO:
    746       strcpy (level_prefix, "INFO");
    747       break;
    748     case G_LOG_LEVEL_DEBUG:
    749       strcpy (level_prefix, "DEBUG");
    750       break;
    751     default:
    752       if (log_level)
    753 	{
    754 	  strcpy (level_prefix, "LOG-");
    755 	  format_unsigned (level_prefix + 4, log_level & G_LOG_LEVEL_MASK, 16);
    756 	}
    757       else
    758 	strcpy (level_prefix, "LOG");
    759       break;
    760     }
    761   if (log_level & G_LOG_FLAG_RECURSION)
    762     strcat (level_prefix, " (recursed)");
    763   if (log_level & ALERT_LEVELS)
    764     strcat (level_prefix, " **");
    765 
    766 #ifdef G_OS_WIN32
    767   win32_keep_fatal_message = (log_level & G_LOG_FLAG_FATAL) != 0;
    768 #endif
    769   return to_stdout ? 1 : 2;
    770 }
    771 
    772 void
    773 _g_log_fallback_handler (const gchar   *log_domain,
    774 			 GLogLevelFlags log_level,
    775 			 const gchar   *message,
    776 			 gpointer       unused_data)
    777 {
    778   gchar level_prefix[STRING_BUFFER_SIZE];
    779 #ifndef G_OS_WIN32
    780   gchar pid_string[FORMAT_UNSIGNED_BUFSIZE];
    781 #endif
    782   gboolean is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
    783   int fd;
    784 
    785   /* we can not call _any_ GLib functions in this fallback handler,
    786    * which is why we skip UTF-8 conversion, etc.
    787    * since we either recursed or ran out of memory, we're in a pretty
    788    * pathologic situation anyways, what we can do is giving the
    789    * the process ID unconditionally however.
    790    */
    791 
    792   fd = mklevel_prefix (level_prefix, log_level);
    793   if (!message)
    794     message = "(NULL) message";
    795 
    796 #ifndef G_OS_WIN32
    797   format_unsigned (pid_string, getpid (), 10);
    798 #endif
    799 
    800   if (log_domain)
    801     write_string (fd, "\n");
    802   else
    803     write_string (fd, "\n** ");
    804 
    805 #ifndef G_OS_WIN32
    806   write_string (fd, "(process:");
    807   write_string (fd, pid_string);
    808   write_string (fd, "): ");
    809 #endif
    810 
    811   if (log_domain)
    812     {
    813       write_string (fd, log_domain);
    814       write_string (fd, "-");
    815     }
    816   write_string (fd, level_prefix);
    817   write_string (fd, ": ");
    818   write_string (fd, message);
    819   if (is_fatal)
    820     write_string (fd, "\naborting...\n");
    821   else
    822     write_string (fd, "\n");
    823 }
    824 
    825 static void
    826 escape_string (GString *string)
    827 {
    828   const char *p = string->str;
    829   gunichar wc;
    830 
    831   while (p < string->str + string->len)
    832     {
    833       gboolean safe;
    834 
    835       wc = g_utf8_get_char_validated (p, -1);
    836       if (wc == (gunichar)-1 || wc == (gunichar)-2)
    837 	{
    838 	  gchar *tmp;
    839 	  guint pos;
    840 
    841 	  pos = p - string->str;
    842 
    843 	  /* Emit invalid UTF-8 as hex escapes
    844            */
    845 	  tmp = g_strdup_printf ("\\x%02x", (guint)(guchar)*p);
    846 	  g_string_erase (string, pos, 1);
    847 	  g_string_insert (string, pos, tmp);
    848 
    849 	  p = string->str + (pos + 4); /* Skip over escape sequence */
    850 
    851 	  g_free (tmp);
    852 	  continue;
    853 	}
    854       if (wc == '\r')
    855 	{
    856 	  safe = *(p + 1) == '\n';
    857 	}
    858       else
    859 	{
    860 	  safe = CHAR_IS_SAFE (wc);
    861 	}
    862 
    863       if (!safe)
    864 	{
    865 	  gchar *tmp;
    866 	  guint pos;
    867 
    868 	  pos = p - string->str;
    869 
    870 	  /* Largest char we escape is 0x0a, so we don't have to worry
    871 	   * about 8-digit \Uxxxxyyyy
    872 	   */
    873 	  tmp = g_strdup_printf ("\\u%04x", wc);
    874 	  g_string_erase (string, pos, g_utf8_next_char (p) - p);
    875 	  g_string_insert (string, pos, tmp);
    876 	  g_free (tmp);
    877 
    878 	  p = string->str + (pos + 6); /* Skip over escape sequence */
    879 	}
    880       else
    881 	p = g_utf8_next_char (p);
    882     }
    883 }
    884 
    885 void
    886 g_log_default_handler (const gchar   *log_domain,
    887 		       GLogLevelFlags log_level,
    888 		       const gchar   *message,
    889 		       gpointer	      unused_data)
    890 {
    891   gboolean is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
    892   gchar level_prefix[STRING_BUFFER_SIZE], *string;
    893   GString *gstring;
    894   int fd;
    895 
    896   /* we can be called externally with recursion for whatever reason */
    897   if (log_level & G_LOG_FLAG_RECURSION)
    898     {
    899       _g_log_fallback_handler (log_domain, log_level, message, unused_data);
    900       return;
    901     }
    902 
    903   g_messages_prefixed_init ();
    904 
    905   fd = mklevel_prefix (level_prefix, log_level);
    906 
    907   gstring = g_string_new (NULL);
    908   if (log_level & ALERT_LEVELS)
    909     g_string_append (gstring, "\n");
    910   if (!log_domain)
    911     g_string_append (gstring, "** ");
    912 
    913   if ((g_log_msg_prefix & log_level) == log_level)
    914     {
    915       const gchar *prg_name = g_get_prgname ();
    916 
    917       if (!prg_name)
    918 	g_string_append_printf (gstring, "(process:%lu): ", (gulong)getpid ());
    919       else
    920 	g_string_append_printf (gstring, "(%s:%lu): ", prg_name, (gulong)getpid ());
    921     }
    922 
    923   if (log_domain)
    924     {
    925       g_string_append (gstring, log_domain);
    926       g_string_append_c (gstring, '-');
    927     }
    928   g_string_append (gstring, level_prefix);
    929 
    930   g_string_append (gstring, ": ");
    931   if (!message)
    932     g_string_append (gstring, "(NULL) message");
    933   else
    934     {
    935       GString *msg;
    936       const gchar *charset;
    937 
    938       msg = g_string_new (message);
    939       escape_string (msg);
    940 
    941       if (g_get_charset (&charset))
    942 	g_string_append (gstring, msg->str);	/* charset is UTF-8 already */
    943       else
    944 	{
    945 	  string = strdup_convert (msg->str, charset);
    946 	  g_string_append (gstring, string);
    947 	  g_free (string);
    948 	}
    949 
    950       g_string_free (msg, TRUE);
    951     }
    952   if (is_fatal)
    953     g_string_append (gstring, "\naborting...\n");
    954   else
    955     g_string_append (gstring, "\n");
    956 
    957   string = g_string_free (gstring, FALSE);
    958 
    959   write_string (fd, string);
    960   g_free (string);
    961 }
    962 
    963 GPrintFunc
    964 g_set_print_handler (GPrintFunc func)
    965 {
    966   GPrintFunc old_print_func;
    967 
    968   g_mutex_lock (g_messages_lock);
    969   old_print_func = glib_print_func;
    970   glib_print_func = func;
    971   g_mutex_unlock (g_messages_lock);
    972 
    973   return old_print_func;
    974 }
    975 
    976 void
    977 g_print (const gchar *format,
    978 	 ...)
    979 {
    980   va_list args;
    981   gchar *string;
    982   GPrintFunc local_glib_print_func;
    983 
    984   g_return_if_fail (format != NULL);
    985 
    986   va_start (args, format);
    987   string = g_strdup_vprintf (format, args);
    988   va_end (args);
    989 
    990   g_mutex_lock (g_messages_lock);
    991   local_glib_print_func = glib_print_func;
    992   g_mutex_unlock (g_messages_lock);
    993 
    994   if (local_glib_print_func)
    995     local_glib_print_func (string);
    996   else
    997     {
    998       const gchar *charset;
    999 
   1000       if (g_get_charset (&charset))
   1001 	fputs (string, stdout); /* charset is UTF-8 already */
   1002       else
   1003 	{
   1004 	  gchar *lstring = strdup_convert (string, charset);
   1005 
   1006 	  fputs (lstring, stdout);
   1007 	  g_free (lstring);
   1008 	}
   1009       fflush (stdout);
   1010     }
   1011   g_free (string);
   1012 }
   1013 
   1014 GPrintFunc
   1015 g_set_printerr_handler (GPrintFunc func)
   1016 {
   1017   GPrintFunc old_printerr_func;
   1018 
   1019   g_mutex_lock (g_messages_lock);
   1020   old_printerr_func = glib_printerr_func;
   1021   glib_printerr_func = func;
   1022   g_mutex_unlock (g_messages_lock);
   1023 
   1024   return old_printerr_func;
   1025 }
   1026 
   1027 void
   1028 g_printerr (const gchar *format,
   1029 	    ...)
   1030 {
   1031   va_list args;
   1032   gchar *string;
   1033   GPrintFunc local_glib_printerr_func;
   1034 
   1035   g_return_if_fail (format != NULL);
   1036 
   1037   va_start (args, format);
   1038   string = g_strdup_vprintf (format, args);
   1039   va_end (args);
   1040 
   1041   g_mutex_lock (g_messages_lock);
   1042   local_glib_printerr_func = glib_printerr_func;
   1043   g_mutex_unlock (g_messages_lock);
   1044 
   1045   if (local_glib_printerr_func)
   1046     local_glib_printerr_func (string);
   1047   else
   1048     {
   1049       const gchar *charset;
   1050 
   1051       if (g_get_charset (&charset))
   1052 	fputs (string, stderr); /* charset is UTF-8 already */
   1053       else
   1054 	{
   1055 	  gchar *lstring = strdup_convert (string, charset);
   1056 
   1057 	  fputs (lstring, stderr);
   1058 	  g_free (lstring);
   1059 	}
   1060       fflush (stderr);
   1061     }
   1062   g_free (string);
   1063 }
   1064 
   1065 gsize
   1066 g_printf_string_upper_bound (const gchar *format,
   1067 			     va_list      args)
   1068 {
   1069   gchar c;
   1070   return _g_vsnprintf (&c, 1, format, args) + 1;
   1071 }
   1072 
   1073 void
   1074 _g_messages_thread_init_nomessage (void)
   1075 {
   1076   g_messages_lock = g_mutex_new ();
   1077   g_log_depth = g_private_new (NULL);
   1078   g_messages_prefixed_init ();
   1079   _g_debug_init ();
   1080 }
   1081 
   1082 gboolean _g_debug_initialized = FALSE;
   1083 guint _g_debug_flags = 0;
   1084 
   1085 void
   1086 _g_debug_init (void)
   1087 {
   1088   const gchar *val;
   1089 
   1090   _g_debug_initialized = TRUE;
   1091 
   1092   val = g_getenv ("G_DEBUG");
   1093   if (val != NULL)
   1094     {
   1095       const GDebugKey keys[] = {
   1096 	{"fatal_warnings", G_DEBUG_FATAL_WARNINGS},
   1097 	{"fatal_criticals", G_DEBUG_FATAL_CRITICALS}
   1098       };
   1099 
   1100       _g_debug_flags = g_parse_debug_string (val, keys, G_N_ELEMENTS (keys));
   1101     }
   1102 
   1103   if (_g_debug_flags & G_DEBUG_FATAL_WARNINGS)
   1104     {
   1105       GLogLevelFlags fatal_mask;
   1106 
   1107       fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
   1108       fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
   1109       g_log_set_always_fatal (fatal_mask);
   1110     }
   1111 
   1112   if (_g_debug_flags & G_DEBUG_FATAL_CRITICALS)
   1113     {
   1114       GLogLevelFlags fatal_mask;
   1115 
   1116       fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
   1117       fatal_mask |= G_LOG_LEVEL_CRITICAL;
   1118       g_log_set_always_fatal (fatal_mask);
   1119     }
   1120 }
   1121 
   1122 #define __G_MESSAGES_C__
   1123 #include "galiasdef.c"
   1124