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

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