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