source: trunk/third/glib2/glib/gmessages.c @ 18159

Revision 18159, 21.0 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18158, which included commits to RCS files with non-trunk default branches.
Line 
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
48#ifdef G_OS_WIN32
49typedef FILE* GFileDescriptor;
50#else
51typedef gint GFileDescriptor;
52#endif
53
54/* --- structures --- */
55typedef struct _GLogDomain      GLogDomain;
56typedef struct _GLogHandler     GLogHandler;
57struct _GLogDomain
58{
59  gchar         *log_domain;
60  GLogLevelFlags fatal_mask;
61  GLogHandler   *handlers;
62  GLogDomain    *next;
63};
64struct _GLogHandler
65{
66  guint          id;
67  GLogLevelFlags log_level;
68  GLogFunc       log_func;
69  gpointer       data;
70  GLogHandler   *next;
71};
72
73
74/* --- variables --- */
75static GMutex        *g_messages_lock = NULL;
76static GLogDomain    *g_log_domains = NULL;
77static GLogLevelFlags g_log_always_fatal = G_LOG_FATAL_MASK;
78static GPrintFunc     glib_print_func = NULL;
79static GPrintFunc     glib_printerr_func = NULL;
80static GPrivate      *g_log_depth = NULL;
81static GLogLevelFlags g_log_msg_prefix = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_DEBUG;
82
83
84/* --- functions --- */
85#ifdef G_OS_WIN32
86#  define STRICT
87#  include <windows.h>
88#  undef STRICT
89#  include <process.h>          /* For _getpid() */
90static gboolean alloc_console_called = FALSE;
91static gboolean win32_keep_fatal_message = FALSE;
92
93/* This default message will usually be overwritten. */
94/* Yes, a fixed size buffer is bad. So sue me. But g_error is never
95 * with huge strings, is it?
96 */
97static gchar  fatal_msg_buf[1000] = "Unspecified fatal error encountered, aborting.";
98static gchar *fatal_msg_ptr = fatal_msg_buf;
99
100/* Just use stdio. If we're out of memory, we're hosed anyway. */
101#undef write
102static inline int
103dowrite (GFileDescriptor fd,
104         const void  *buf,
105         unsigned int len)
106{
107  if (win32_keep_fatal_message)
108    {
109      memcpy (fatal_msg_ptr, buf, len);
110      fatal_msg_ptr += len;
111      *fatal_msg_ptr = 0;
112      return len;
113    }
114
115  fwrite (buf, len, 1, fd);
116  fflush (fd);
117
118  return len;
119}
120#define write(fd, buf, len) dowrite(fd, buf, len)
121
122static void
123ensure_stdout_valid (void)
124{
125  HANDLE handle;
126
127  if (win32_keep_fatal_message)
128    return;
129
130  if (!alloc_console_called)
131    {
132      handle = GetStdHandle (STD_OUTPUT_HANDLE);
133 
134      if (handle == INVALID_HANDLE_VALUE)
135        {
136          AllocConsole ();
137          alloc_console_called = TRUE;
138          freopen ("CONOUT$", "w", stdout);
139        }
140    }
141}
142#else
143#define ensure_stdout_valid()   /* Define as empty */
144#endif
145
146static void
147write_string (GFileDescriptor fd,
148              const gchar    *string)
149{
150  write (fd, string, strlen (string));
151}
152
153static void
154g_messages_prefixed_init (void)
155{
156  static gboolean initialized = FALSE;
157
158  if (!initialized)
159    {
160      const gchar *val;
161
162      initialized = TRUE;
163      val = g_getenv ("G_MESSAGES_PREFIXED");
164     
165      if (val)
166        {
167          static const GDebugKey keys[] = {
168            { "error", G_LOG_LEVEL_ERROR },
169            { "critical", G_LOG_LEVEL_CRITICAL },
170            { "warning", G_LOG_LEVEL_WARNING },
171            { "message", G_LOG_LEVEL_MESSAGE },
172            { "info", G_LOG_LEVEL_INFO },
173            { "debug", G_LOG_LEVEL_DEBUG }
174          };
175         
176          g_log_msg_prefix = g_parse_debug_string (val, keys, G_N_ELEMENTS (keys));
177        }
178    }
179}
180
181static GLogDomain*
182g_log_find_domain_L (const gchar *log_domain)
183{
184  register GLogDomain *domain;
185 
186  domain = g_log_domains;
187  while (domain)
188    {
189      if (strcmp (domain->log_domain, log_domain) == 0)
190        return domain;
191      domain = domain->next;
192    }
193  return NULL;
194}
195
196static GLogDomain*
197g_log_domain_new_L (const gchar *log_domain)
198{
199  register GLogDomain *domain;
200
201  domain = g_new (GLogDomain, 1);
202  domain->log_domain = g_strdup (log_domain);
203  domain->fatal_mask = G_LOG_FATAL_MASK;
204  domain->handlers = NULL;
205 
206  domain->next = g_log_domains;
207  g_log_domains = domain;
208 
209  return domain;
210}
211
212static void
213g_log_domain_check_free_L (GLogDomain *domain)
214{
215  if (domain->fatal_mask == G_LOG_FATAL_MASK &&
216      domain->handlers == NULL)
217    {
218      register GLogDomain *last, *work;
219     
220      last = NULL; 
221
222      work = g_log_domains;
223      while (work)
224        {
225          if (work == domain)
226            {
227              if (last)
228                last->next = domain->next;
229              else
230                g_log_domains = domain->next;
231              g_free (domain->log_domain);
232              g_free (domain);
233              break;
234            }
235          last = work;
236          work = last->next;
237        } 
238    }
239}
240
241static GLogFunc
242g_log_domain_get_handler_L (GLogDomain  *domain,
243                            GLogLevelFlags log_level,
244                            gpointer    *data)
245{
246  if (domain && log_level)
247    {
248      register GLogHandler *handler;
249     
250      handler = domain->handlers;
251      while (handler)
252        {
253          if ((handler->log_level & log_level) == log_level)
254            {
255              *data = handler->data;
256              return handler->log_func;
257            }
258          handler = handler->next;
259        }
260    }
261  return g_log_default_handler;
262}
263
264GLogLevelFlags
265g_log_set_always_fatal (GLogLevelFlags fatal_mask)
266{
267  GLogLevelFlags old_mask;
268
269  /* restrict the global mask to levels that are known to glib
270   * since this setting applies to all domains
271   */
272  fatal_mask &= (1 << G_LOG_LEVEL_USER_SHIFT) - 1;
273  /* force errors to be fatal */
274  fatal_mask |= G_LOG_LEVEL_ERROR;
275  /* remove bogus flag */
276  fatal_mask &= ~G_LOG_FLAG_FATAL;
277
278  g_mutex_lock (g_messages_lock);
279  old_mask = g_log_always_fatal;
280  g_log_always_fatal = fatal_mask;
281  g_mutex_unlock (g_messages_lock);
282
283  return old_mask;
284}
285
286GLogLevelFlags
287g_log_set_fatal_mask (const gchar   *log_domain,
288                      GLogLevelFlags fatal_mask)
289{
290  GLogLevelFlags old_flags;
291  register GLogDomain *domain;
292 
293  if (!log_domain)
294    log_domain = "";
295 
296  /* force errors to be fatal */
297  fatal_mask |= G_LOG_LEVEL_ERROR;
298  /* remove bogus flag */
299  fatal_mask &= ~G_LOG_FLAG_FATAL;
300 
301  g_mutex_lock (g_messages_lock);
302
303  domain = g_log_find_domain_L (log_domain);
304  if (!domain)
305    domain = g_log_domain_new_L (log_domain);
306  old_flags = domain->fatal_mask;
307 
308  domain->fatal_mask = fatal_mask;
309  g_log_domain_check_free_L (domain);
310
311  g_mutex_unlock (g_messages_lock);
312
313  return old_flags;
314}
315
316guint
317g_log_set_handler (const gchar   *log_domain,
318                   GLogLevelFlags log_levels,
319                   GLogFunc       log_func,
320                   gpointer       user_data)
321{
322  static guint handler_id = 0;
323  GLogDomain *domain;
324  GLogHandler *handler;
325 
326  g_return_val_if_fail ((log_levels & G_LOG_LEVEL_MASK) != 0, 0);
327  g_return_val_if_fail (log_func != NULL, 0);
328 
329  if (!log_domain)
330    log_domain = "";
331
332  handler = g_new (GLogHandler, 1);
333
334  g_mutex_lock (g_messages_lock);
335
336  domain = g_log_find_domain_L (log_domain);
337  if (!domain)
338    domain = g_log_domain_new_L (log_domain);
339 
340  handler->id = ++handler_id;
341  handler->log_level = log_levels;
342  handler->log_func = log_func;
343  handler->data = user_data;
344  handler->next = domain->handlers;
345  domain->handlers = handler;
346
347  g_mutex_unlock (g_messages_lock);
348 
349  return handler_id;
350}
351
352void
353g_log_remove_handler (const gchar *log_domain,
354                      guint        handler_id)
355{
356  register GLogDomain *domain;
357 
358  g_return_if_fail (handler_id > 0);
359 
360  if (!log_domain)
361    log_domain = "";
362 
363  g_mutex_lock (g_messages_lock);
364  domain = g_log_find_domain_L (log_domain);
365  if (domain)
366    {
367      GLogHandler *work, *last;
368     
369      last = NULL;
370      work = domain->handlers;
371      while (work)
372        {
373          if (work->id == handler_id)
374            {
375              if (last)
376                last->next = work->next;
377              else
378                domain->handlers = work->next;
379              g_log_domain_check_free_L (domain);
380              g_mutex_unlock (g_messages_lock);
381              g_free (work);
382              return;
383            }
384          last = work;
385          work = last->next;
386        }
387    }
388  g_mutex_unlock (g_messages_lock);
389  g_warning ("%s: could not find handler with id `%d' for domain \"%s\"",
390             G_STRLOC, handler_id, log_domain);
391}
392
393void
394g_logv (const gchar   *log_domain,
395        GLogLevelFlags log_level,
396        const gchar   *format,
397        va_list        args1)
398{
399  gchar buffer[1025];
400  gboolean was_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
401  gboolean was_recursion = (log_level & G_LOG_FLAG_RECURSION) != 0;
402  gint i;
403
404  log_level &= G_LOG_LEVEL_MASK;
405  if (!log_level)
406    return;
407 
408  /* we use a stack buffer of fixed size, because we might get called
409   * recursively.
410   */
411  _g_vsnprintf (buffer, 1024, format, args1);
412 
413  for (i = g_bit_nth_msf (log_level, -1); i >= 0; i = g_bit_nth_msf (log_level, i))
414    {
415      register GLogLevelFlags test_level;
416     
417      test_level = 1 << i;
418      if (log_level & test_level)
419        {
420          guint depth = GPOINTER_TO_UINT (g_private_get (g_log_depth));
421          GLogDomain *domain;
422          GLogFunc log_func;
423          guint domain_fatal_mask;
424          gpointer data = NULL;
425
426          if (was_fatal)
427            test_level |= G_LOG_FLAG_FATAL;
428          if (was_recursion)
429            test_level |= G_LOG_FLAG_RECURSION;
430
431          /* check recursion and lookup handler */
432          g_mutex_lock (g_messages_lock);
433          domain = g_log_find_domain_L (log_domain ? log_domain : "");
434          if (depth)
435            test_level |= G_LOG_FLAG_RECURSION;
436          depth++;
437          domain_fatal_mask = domain ? domain->fatal_mask : G_LOG_FATAL_MASK;
438          if ((domain_fatal_mask | g_log_always_fatal) & test_level)
439            test_level |= G_LOG_FLAG_FATAL;
440          if (test_level & G_LOG_FLAG_RECURSION)
441            log_func = _g_log_fallback_handler;
442          else
443            log_func = g_log_domain_get_handler_L (domain, test_level, &data);
444          domain = NULL;
445          g_mutex_unlock (g_messages_lock);
446
447          g_private_set (g_log_depth, GUINT_TO_POINTER (depth));
448
449          /* had to defer debug initialization until we can keep track of recursion */
450          if (!(test_level & G_LOG_FLAG_RECURSION) && !_g_debug_initialized)
451            {
452              guint orig_test_level = test_level;
453
454              _g_debug_init ();
455              if ((domain_fatal_mask | g_log_always_fatal) & test_level)
456                test_level |= G_LOG_FLAG_FATAL;
457              if (test_level != orig_test_level)
458                {
459                  /* need a relookup, not nice, but not too bad either */
460                  g_mutex_lock (g_messages_lock);
461                  domain = g_log_find_domain_L (log_domain ? log_domain : "");
462                  log_func = g_log_domain_get_handler_L (domain, test_level, &data);
463                  domain = NULL;
464                  g_mutex_unlock (g_messages_lock);
465                }
466            }
467
468          log_func (log_domain, test_level, buffer, data);
469
470          if (test_level & G_LOG_FLAG_FATAL)
471            {
472#ifdef G_OS_WIN32
473              MessageBox (NULL, fatal_msg_buf, NULL, MB_OK);
474#endif
475#if defined (G_ENABLE_DEBUG) && (defined (SIGTRAP) || defined (G_OS_WIN32))
476              if (!(test_level & G_LOG_FLAG_RECURSION))
477                G_BREAKPOINT ();
478              else
479                abort ();
480#else /* !G_ENABLE_DEBUG || !(SIGTRAP || G_OS_WIN32) */
481              abort ();
482#endif /* !G_ENABLE_DEBUG || !(SIGTRAP || G_OS_WIN32) */
483            }
484         
485          depth--;
486          g_private_set (g_log_depth, GUINT_TO_POINTER (depth));
487        }
488    }
489}
490
491void
492g_log (const gchar   *log_domain,
493       GLogLevelFlags log_level,
494       const gchar   *format,
495       ...)
496{
497  va_list args;
498 
499  va_start (args, format);
500  g_logv (log_domain, log_level, format, args);
501  va_end (args);
502}
503
504static gchar*
505strdup_convert (const gchar *string,
506                const gchar *charset)
507{
508  if (!g_utf8_validate (string, -1, NULL))
509    return g_strconcat ("[Invalid UTF-8] ", string, NULL);
510  else
511    {
512      GError *err = NULL;
513     
514      gchar *result = g_convert_with_fallback (string, -1, charset, "UTF-8", "?", NULL, NULL, &err);
515      if (result)
516        return result;
517      else
518        {
519          /* Not thread-safe, but doesn't matter if we print the warning twice
520           */
521          static gboolean warned = FALSE;
522          if (!warned)
523            {
524              warned = TRUE;
525              _g_fprintf (stderr, "GLib: Cannot convert message: %s\n", err->message);
526            }
527          g_error_free (err);
528         
529          return g_strdup (string);
530        }
531    }
532}
533
534/* For a radix of 8 we need at most 3 output bytes for 1 input
535 * byte. Additionally we might need up to 2 output bytes for the
536 * readix prefix and 1 byte for the trailing NULL.
537 */
538#define FORMAT_UNSIGNED_BUFSIZE ((GLIB_SIZEOF_LONG * 3) + 3)
539
540static void
541format_unsigned (gchar  *buf,
542                 gulong  num,
543                 guint   radix)
544{
545  gulong tmp;
546  gchar c;
547  gint i, n;
548
549  /* we may not call _any_ GLib functions here (or macros like g_return_if_fail()) */
550
551  if (radix != 8 && radix != 10 && radix != 16)
552    {
553      *buf = '\000';
554      return;
555    }
556 
557  if (!num)
558    {
559      *buf++ = '0';
560      *buf = '\000';
561      return;
562    }
563 
564  if (radix == 16)
565    {
566      *buf++ = '0';
567      *buf++ = 'x';
568    }
569  else if (radix == 8)
570    {
571      *buf++ = '0';
572    }
573       
574  n = 0;
575  tmp = num;
576  while (tmp)
577    {
578      tmp /= radix;
579      n++;
580    }
581
582  i = n;
583
584  /* Again we can't use g_assert; actually this check should _never_ fail. */
585  if (n > FORMAT_UNSIGNED_BUFSIZE - 3)
586    {
587      *buf = '\000';
588      return;
589    }
590
591  while (num)
592    {
593      i--;
594      c = (num % radix);
595      if (c < 10)
596        buf[i] = c + '0';
597      else
598        buf[i] = c + 'a' - 10;
599      num /= radix;
600    }
601 
602  buf[n] = '\000';
603}
604
605/* string size big enough to hold level prefix */
606#define STRING_BUFFER_SIZE      (FORMAT_UNSIGNED_BUFSIZE + 32)
607
608#define ALERT_LEVELS            (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING)
609
610static GFileDescriptor
611mklevel_prefix (gchar level_prefix[STRING_BUFFER_SIZE],
612                guint log_level)
613{
614  gboolean to_stdout = TRUE;
615
616  /* we may not call _any_ GLib functions here */
617
618  switch (log_level & G_LOG_LEVEL_MASK)
619    {
620    case G_LOG_LEVEL_ERROR:
621      strcpy (level_prefix, "ERROR");
622      to_stdout = FALSE;
623      break;
624    case G_LOG_LEVEL_CRITICAL:
625      strcpy (level_prefix, "CRITICAL");
626      to_stdout = FALSE;
627      break;
628    case G_LOG_LEVEL_WARNING:
629      strcpy (level_prefix, "WARNING");
630      to_stdout = FALSE;
631      break;
632    case G_LOG_LEVEL_MESSAGE:
633      strcpy (level_prefix, "Message");
634      to_stdout = FALSE;
635      break;
636    case G_LOG_LEVEL_INFO:
637      strcpy (level_prefix, "INFO");
638      break;
639    case G_LOG_LEVEL_DEBUG:
640      strcpy (level_prefix, "DEBUG");
641      break;
642    default:
643      if (log_level)
644        {
645          strcpy (level_prefix, "LOG-");
646          format_unsigned (level_prefix + 4, log_level & G_LOG_LEVEL_MASK, 16);
647        }
648      else
649        strcpy (level_prefix, "LOG");
650      break;
651    }
652  if (log_level & G_LOG_FLAG_RECURSION)
653    strcat (level_prefix, " (recursed)");
654  if (log_level & ALERT_LEVELS)
655    strcat (level_prefix, " **");
656
657  ensure_stdout_valid ();
658#ifdef G_OS_WIN32
659  win32_keep_fatal_message = (log_level & G_LOG_FLAG_FATAL) != 0;
660  /* Use just stdout as stderr is hard to get redirected from the DOS prompt. */
661  return stdout;
662#else
663  return to_stdout ? 1 : 2;
664#endif
665}
666
667void
668_g_log_fallback_handler (const gchar   *log_domain,
669                         GLogLevelFlags log_level,
670                         const gchar   *message,
671                         gpointer       unused_data)
672{
673  gchar level_prefix[STRING_BUFFER_SIZE], pid_string[FORMAT_UNSIGNED_BUFSIZE];
674  gboolean is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
675  GFileDescriptor fd;
676
677  /* we can not call _any_ GLib functions in this fallback handler,
678   * which is why we skip UTF-8 conversion, etc.
679   * since we either recursed or ran out of memory, we're in a pretty
680   * pathologic situation anyways, what we can do is giving the
681   * the process ID unconditionally however.
682   */
683
684  fd = mklevel_prefix (level_prefix, log_level);
685  if (!message)
686    message = "(NULL) message";
687
688  format_unsigned (pid_string, getpid (), 10);
689
690  if (log_domain)
691    write_string (fd, "\n");
692  else
693    write_string (fd, "\n** ");
694  write_string (fd, "(process:");
695  write_string (fd, pid_string);
696  write_string (fd, "): ");
697  if (log_domain)
698    {
699      write_string (fd, log_domain);
700      write_string (fd, "-");
701    }
702  write_string (fd, level_prefix);
703  write_string (fd, ": ");
704  write_string (fd, message);
705  if (is_fatal)
706    write_string (fd, "\naborting...\n");
707  else
708    write_string (fd, "\n");
709}
710
711void
712g_log_default_handler (const gchar   *log_domain,
713                       GLogLevelFlags log_level,
714                       const gchar   *message,
715                       gpointer       unused_data)
716{
717  gboolean is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
718  gchar level_prefix[STRING_BUFFER_SIZE], *string;
719  GString *gstring;
720  GFileDescriptor fd;
721
722  /* we can be called externally with recursion for whatever reason */
723  if (log_level & G_LOG_FLAG_RECURSION)
724    {
725      _g_log_fallback_handler (log_domain, log_level, message, unused_data);
726      return;
727    }
728
729  g_messages_prefixed_init ();
730
731  fd = mklevel_prefix (level_prefix, log_level);
732
733  gstring = g_string_new ("");
734  if (log_level & ALERT_LEVELS)
735    g_string_append (gstring, "\n");
736  if (!log_domain)
737    g_string_append (gstring, "** ");
738
739  if ((g_log_msg_prefix & log_level) == log_level)
740    {
741      const gchar *prg_name = g_get_prgname ();
742     
743      if (!prg_name)
744        g_string_append_printf (gstring, "(process:%lu): ", (gulong)getpid ());
745      else
746        g_string_append_printf (gstring, "(%s:%lu): ", prg_name, (gulong)getpid ());
747    }
748
749  if (log_domain)
750    {
751      g_string_append (gstring, log_domain);
752      g_string_append_c (gstring, '-');
753    }
754  g_string_append (gstring, level_prefix);
755
756  g_string_append (gstring, ": ");
757  if (!message)
758    g_string_append (gstring, "(NULL) message");
759  else
760    {
761      const gchar *charset;
762
763      if (g_get_charset (&charset))
764        g_string_append (gstring, message);     /* charset is UTF-8 already */
765      else
766        {
767          string = strdup_convert (message, charset);
768          g_string_append (gstring, string);
769          g_free (string);
770        }
771    }
772  if (is_fatal)
773    g_string_append (gstring, "\naborting...\n");
774  else
775    g_string_append (gstring, "\n");
776
777  string = g_string_free (gstring, FALSE);
778
779  write_string (fd, string);
780  g_free (string);
781}
782
783GPrintFunc
784g_set_print_handler (GPrintFunc func)
785{
786  GPrintFunc old_print_func;
787 
788  g_mutex_lock (g_messages_lock);
789  old_print_func = glib_print_func;
790  glib_print_func = func;
791  g_mutex_unlock (g_messages_lock);
792 
793  return old_print_func;
794}
795
796void
797g_print (const gchar *format,
798         ...)
799{
800  va_list args;
801  gchar *string;
802  GPrintFunc local_glib_print_func;
803 
804  g_return_if_fail (format != NULL);
805 
806  va_start (args, format);
807  string = g_strdup_vprintf (format, args);
808  va_end (args);
809 
810  g_mutex_lock (g_messages_lock);
811  local_glib_print_func = glib_print_func;
812  g_mutex_unlock (g_messages_lock);
813 
814  if (local_glib_print_func)
815    local_glib_print_func (string);
816  else
817    {
818      const gchar *charset;
819
820      ensure_stdout_valid ();
821      if (g_get_charset (&charset))
822        fputs (string, stdout); /* charset is UTF-8 already */
823      else
824        {
825          gchar *lstring = strdup_convert (string, charset);
826
827          fputs (lstring, stdout);
828          g_free (lstring);
829        }
830      fflush (stdout);
831    }
832  g_free (string);
833}
834
835GPrintFunc
836g_set_printerr_handler (GPrintFunc func)
837{
838  GPrintFunc old_printerr_func;
839 
840  g_mutex_lock (g_messages_lock);
841  old_printerr_func = glib_printerr_func;
842  glib_printerr_func = func;
843  g_mutex_unlock (g_messages_lock);
844 
845  return old_printerr_func;
846}
847
848void
849g_printerr (const gchar *format,
850            ...)
851{
852  va_list args;
853  gchar *string;
854  GPrintFunc local_glib_printerr_func;
855 
856  g_return_if_fail (format != NULL);
857 
858  va_start (args, format);
859  string = g_strdup_vprintf (format, args);
860  va_end (args);
861 
862  g_mutex_lock (g_messages_lock);
863  local_glib_printerr_func = glib_printerr_func;
864  g_mutex_unlock (g_messages_lock);
865 
866  if (local_glib_printerr_func)
867    local_glib_printerr_func (string);
868  else
869    {
870      const gchar *charset;
871
872      if (g_get_charset (&charset))
873        fputs (string, stderr); /* charset is UTF-8 already */
874      else
875        {
876          gchar *lstring = strdup_convert (string, charset);
877
878          fputs (lstring, stderr);
879          g_free (lstring);
880        }
881      fflush (stderr);
882    }
883  g_free (string);
884}
885
886gsize
887g_printf_string_upper_bound (const gchar *format,
888                             va_list      args)
889{
890  gchar c;
891  return _g_vsnprintf (&c, 1, format, args) + 1;
892}
893
894void
895g_messages_init (void)
896{
897  g_messages_lock = g_mutex_new ();
898  g_log_depth = g_private_new (NULL);
899  g_messages_prefixed_init ();
900  _g_debug_init ();
901}
902
903gboolean _g_debug_initialized = FALSE;
904guint _g_debug_flags = 0;
905
906void
907_g_debug_init (void)
908{
909  const gchar *val;
910 
911  _g_debug_initialized = TRUE;
912 
913  val = g_getenv ("G_DEBUG");
914  if (val != NULL)
915    {
916      static const GDebugKey keys[] = {
917        {"fatal_warnings", G_DEBUG_FATAL_WARNINGS}
918      };
919     
920      _g_debug_flags = g_parse_debug_string (val, keys, G_N_ELEMENTS (keys));
921    }
922 
923  if (_g_debug_flags & G_DEBUG_FATAL_WARNINGS)
924    {
925      GLogLevelFlags fatal_mask;
926     
927      fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
928      fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
929      g_log_set_always_fatal (fatal_mask);
930    }
931}
Note: See TracBrowser for help on using the repository browser.