gmessages.c 24.4 KB
Newer Older
Owen Taylor's avatar
Owen Taylor committed
1 2 3 4
/* GLIB - Library of useful routines for C programming
 * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
Owen Taylor's avatar
Owen Taylor committed
6 7 8 9 10
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * 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.
Owen Taylor's avatar
Owen Taylor committed
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
Owen Taylor's avatar
Owen Taylor committed
15 16 17 18
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
19

20
/*
21
 * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
22 23 24 25 26
 * file for a list of people on the GLib Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
 * GLib at ftp://ftp.gtk.org/pub/gtk/. 
 */

27 28 29 30
/* 
 * MT safe
 */

31
#include "config.h"
32

33
#include <stdlib.h>
Owen Taylor's avatar
Owen Taylor committed
34 35 36
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
37 38 39
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
40
#include <signal.h>
41 42
#include <locale.h>
#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 54 55 56
#  define STRICT		/* Strict typing, please */
#  define _WIN32_WINDOWS 0x0401 /* to get IsDebuggerPresent */
#  include <windows.h>
#  undef STRICT
57
#endif
Owen Taylor's avatar
Owen Taylor committed
58

59 60 61 62
/* --- structures --- */
typedef struct _GLogDomain	GLogDomain;
typedef struct _GLogHandler	GLogHandler;
struct _GLogDomain
Owen Taylor's avatar
Owen Taylor committed
63
{
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
  gchar		*log_domain;
  GLogLevelFlags fatal_mask;
  GLogHandler	*handlers;
  GLogDomain	*next;
};
struct _GLogHandler
{
  guint		 id;
  GLogLevelFlags log_level;
  GLogFunc	 log_func;
  gpointer	 data;
  GLogHandler	*next;
};


/* --- 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 84
static GPrintFunc     glib_print_func = NULL;
static GPrintFunc     glib_printerr_func = NULL;
85 86
static GPrivate	     *g_log_depth = NULL;
static GLogLevelFlags g_log_msg_prefix = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_DEBUG;
87 88
static GLogFunc       default_log_func = g_log_default_handler;
static gpointer       default_log_data = NULL;
89

90
/* --- functions --- */
91 92 93
#ifdef G_OS_WIN32
#  define STRICT
#  include <windows.h>
94
#  undef STRICT
95
static gboolean win32_keep_fatal_message = FALSE;
96 97

/* This default message will usually be overwritten. */
98 99
/* Yes, a fixed size buffer is bad. So sue me. But g_error() is never
 * called with huge strings, is it?
100 101 102
 */
static gchar  fatal_msg_buf[1000] = "Unspecified fatal error encountered, aborting.";
static gchar *fatal_msg_ptr = fatal_msg_buf;
103

104 105
#undef write
static inline int
106
dowrite (int          fd,
107 108
	 const void  *buf,
	 unsigned int len)
109
{
110
  if (win32_keep_fatal_message)
111 112 113 114 115 116 117
    {
      memcpy (fatal_msg_ptr, buf, len);
      fatal_msg_ptr += len;
      *fatal_msg_ptr = 0;
      return len;
    }

118
  write (fd, buf, len);
119 120 121

  return len;
}
122 123
#define write(fd, buf, len) dowrite(fd, buf, len)

124
#endif
125

126
static void
127 128
write_string (int          fd,
	      const gchar *string)
129 130 131 132
{
  write (fd, string, strlen (string));
}

133 134
static void
g_messages_prefixed_init (void)
135 136 137
{
  static gboolean initialized = FALSE;

138
  if (!initialized)
139
    {
140
      const gchar *val;
141

142 143 144 145
      initialized = TRUE;
      val = g_getenv ("G_MESSAGES_PREFIXED");
      
      if (val)
146
	{
147
	  const GDebugKey keys[] = {
148 149 150 151 152 153 154 155 156
	    { "error", G_LOG_LEVEL_ERROR },
	    { "critical", G_LOG_LEVEL_CRITICAL },
	    { "warning", G_LOG_LEVEL_WARNING },
	    { "message", G_LOG_LEVEL_MESSAGE },
	    { "info", G_LOG_LEVEL_INFO },
	    { "debug", G_LOG_LEVEL_DEBUG }
	  };
	  
	  g_log_msg_prefix = g_parse_debug_string (val, keys, G_N_ELEMENTS (keys));
157
	}
158 159 160
    }
}

161 162
static GLogDomain*
g_log_find_domain_L (const gchar *log_domain)
163 164
{
  register GLogDomain *domain;
165
  
166 167
  domain = g_log_domains;
  while (domain)
Owen Taylor's avatar
Owen Taylor committed
168
    {
169
      if (strcmp (domain->log_domain, log_domain) == 0)
170
	return domain;
171
      domain = domain->next;
Owen Taylor's avatar
Owen Taylor committed
172
    }
173 174 175
  return NULL;
}

176 177
static GLogDomain*
g_log_domain_new_L (const gchar *log_domain)
178 179
{
  register GLogDomain *domain;
180

181 182 183 184
  domain = g_new (GLogDomain, 1);
  domain->log_domain = g_strdup (log_domain);
  domain->fatal_mask = G_LOG_FATAL_MASK;
  domain->handlers = NULL;
185
  
186 187 188 189 190
  domain->next = g_log_domains;
  g_log_domains = domain;
  
  return domain;
}
Owen Taylor's avatar
Owen Taylor committed
191

192 193
static void
g_log_domain_check_free_L (GLogDomain *domain)
194 195 196
{
  if (domain->fatal_mask == G_LOG_FATAL_MASK &&
      domain->handlers == NULL)
Owen Taylor's avatar
Owen Taylor committed
197
    {
198 199
      register GLogDomain *last, *work;
      
200 201
      last = NULL;  

202 203 204 205 206 207 208 209 210 211 212 213 214
      work = g_log_domains;
      while (work)
	{
	  if (work == domain)
	    {
	      if (last)
		last->next = domain->next;
	      else
		g_log_domains = domain->next;
	      g_free (domain->log_domain);
	      g_free (domain);
	      break;
	    }
215 216
	  last = work;
	  work = last->next;
217
	}  
Owen Taylor's avatar
Owen Taylor committed
218
    }
219 220
}

221 222 223 224
static GLogFunc
g_log_domain_get_handler_L (GLogDomain	*domain,
			    GLogLevelFlags log_level,
			    gpointer	*data)
225 226
{
  if (domain && log_level)
Owen Taylor's avatar
Owen Taylor committed
227
    {
228 229 230 231 232 233 234 235 236 237 238 239
      register GLogHandler *handler;
      
      handler = domain->handlers;
      while (handler)
	{
	  if ((handler->log_level & log_level) == log_level)
	    {
	      *data = handler->data;
	      return handler->log_func;
	    }
	  handler = handler->next;
	}
Owen Taylor's avatar
Owen Taylor committed
240
    }
241 242 243

  *data = default_log_data;
  return default_log_func;
244 245
}

246 247 248 249 250
GLogLevelFlags
g_log_set_always_fatal (GLogLevelFlags fatal_mask)
{
  GLogLevelFlags old_mask;

251 252 253
  /* restrict the global mask to levels that are known to glib
   * since this setting applies to all domains
   */
254 255 256 257 258 259
  fatal_mask &= (1 << G_LOG_LEVEL_USER_SHIFT) - 1;
  /* force errors to be fatal */
  fatal_mask |= G_LOG_LEVEL_ERROR;
  /* remove bogus flag */
  fatal_mask &= ~G_LOG_FLAG_FATAL;

260
  g_mutex_lock (g_messages_lock);
261 262
  old_mask = g_log_always_fatal;
  g_log_always_fatal = fatal_mask;
263
  g_mutex_unlock (g_messages_lock);
264 265 266 267

  return old_mask;
}

268
GLogLevelFlags
269 270
g_log_set_fatal_mask (const gchar   *log_domain,
		      GLogLevelFlags fatal_mask)
271 272 273 274 275 276 277 278 279 280 281 282
{
  GLogLevelFlags old_flags;
  register GLogDomain *domain;
  
  if (!log_domain)
    log_domain = "";
  
  /* force errors to be fatal */
  fatal_mask |= G_LOG_LEVEL_ERROR;
  /* remove bogus flag */
  fatal_mask &= ~G_LOG_FLAG_FATAL;
  
283 284
  g_mutex_lock (g_messages_lock);

285
  domain = g_log_find_domain_L (log_domain);
286
  if (!domain)
287
    domain = g_log_domain_new_L (log_domain);
288 289 290
  old_flags = domain->fatal_mask;
  
  domain->fatal_mask = fatal_mask;
291
  g_log_domain_check_free_L (domain);
292 293 294

  g_mutex_unlock (g_messages_lock);

295 296
  return old_flags;
}
Owen Taylor's avatar
Owen Taylor committed
297

298
guint
299 300 301 302
g_log_set_handler (const gchar	 *log_domain,
		   GLogLevelFlags log_levels,
		   GLogFunc	  log_func,
		   gpointer	  user_data)
303 304
{
  static guint handler_id = 0;
305 306
  GLogDomain *domain;
  GLogHandler *handler;
307 308 309 310 311 312
  
  g_return_val_if_fail ((log_levels & G_LOG_LEVEL_MASK) != 0, 0);
  g_return_val_if_fail (log_func != NULL, 0);
  
  if (!log_domain)
    log_domain = "";
313 314 315

  handler = g_new (GLogHandler, 1);

316 317
  g_mutex_lock (g_messages_lock);

318
  domain = g_log_find_domain_L (log_domain);
319
  if (!domain)
320
    domain = g_log_domain_new_L (log_domain);
321 322 323 324 325 326 327
  
  handler->id = ++handler_id;
  handler->log_level = log_levels;
  handler->log_func = log_func;
  handler->data = user_data;
  handler->next = domain->handlers;
  domain->handlers = handler;
328 329

  g_mutex_unlock (g_messages_lock);
330 331
  
  return handler_id;
Owen Taylor's avatar
Owen Taylor committed
332 333
}

334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
GLogFunc
g_log_set_default_handler (GLogFunc log_func,
			   gpointer user_data)
{
  GLogFunc old_log_func;
  
  g_mutex_lock (g_messages_lock);
  old_log_func = default_log_func;
  default_log_func = log_func;
  default_log_data = user_data;
  g_mutex_unlock (g_messages_lock);
  
  return old_log_func;
}

Owen Taylor's avatar
Owen Taylor committed
349
void
350 351
g_log_remove_handler (const gchar *log_domain,
		      guint	   handler_id)
Owen Taylor's avatar
Owen Taylor committed
352
{
353 354 355 356 357 358 359
  register GLogDomain *domain;
  
  g_return_if_fail (handler_id > 0);
  
  if (!log_domain)
    log_domain = "";
  
360
  g_mutex_lock (g_messages_lock);
361
  domain = g_log_find_domain_L (log_domain);
362 363
  if (domain)
    {
364
      GLogHandler *work, *last;
365 366 367 368 369 370 371 372 373 374 375
      
      last = NULL;
      work = domain->handlers;
      while (work)
	{
	  if (work->id == handler_id)
	    {
	      if (last)
		last->next = work->next;
	      else
		domain->handlers = work->next;
376
	      g_log_domain_check_free_L (domain); 
377
	      g_mutex_unlock (g_messages_lock);
378
	      g_free (work);
379 380
	      return;
	    }
381 382
	  last = work;
	  work = last->next;
383
	}
384 385
    } 
  g_mutex_unlock (g_messages_lock);
386 387
  g_warning ("%s: could not find handler with id `%d' for domain \"%s\"",
	     G_STRLOC, handler_id, log_domain);
388
}
Owen Taylor's avatar
Owen Taylor committed
389

390
void
391 392 393 394
g_logv (const gchar   *log_domain,
	GLogLevelFlags log_level,
	const gchar   *format,
	va_list	       args1)
395
{
396 397 398
  gboolean was_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
  gboolean was_recursion = (log_level & G_LOG_FLAG_RECURSION) != 0;
  gint i;
399

400 401 402 403 404
  log_level &= G_LOG_LEVEL_MASK;
  if (!log_level)
    return;
  
  for (i = g_bit_nth_msf (log_level, -1); i >= 0; i = g_bit_nth_msf (log_level, i))
Owen Taylor's avatar
Owen Taylor committed
405
    {
406 407 408 409 410
      register GLogLevelFlags test_level;
      
      test_level = 1 << i;
      if (log_level & test_level)
	{
411
	  guint depth = GPOINTER_TO_UINT (g_private_get (g_log_depth));
412 413
	  GLogDomain *domain;
	  GLogFunc log_func;
414
	  GLogLevelFlags domain_fatal_mask;
415
	  gpointer data = NULL;
416

417 418 419 420 421 422 423 424
	  if (was_fatal)
	    test_level |= G_LOG_FLAG_FATAL;
	  if (was_recursion)
	    test_level |= G_LOG_FLAG_RECURSION;

	  /* check recursion and lookup handler */
	  g_mutex_lock (g_messages_lock);
	  domain = g_log_find_domain_L (log_domain ? log_domain : "");
425
	  if (depth)
426
	    test_level |= G_LOG_FLAG_RECURSION;
427
	  depth++;
428 429 430 431 432 433 434 435 436 437
	  domain_fatal_mask = domain ? domain->fatal_mask : G_LOG_FATAL_MASK;
	  if ((domain_fatal_mask | g_log_always_fatal) & test_level)
	    test_level |= G_LOG_FLAG_FATAL;
	  if (test_level & G_LOG_FLAG_RECURSION)
	    log_func = _g_log_fallback_handler;
	  else
	    log_func = g_log_domain_get_handler_L (domain, test_level, &data);
	  domain = NULL;
	  g_mutex_unlock (g_messages_lock);

438 439
	  g_private_set (g_log_depth, GUINT_TO_POINTER (depth));

440 441 442
	  /* had to defer debug initialization until we can keep track of recursion */
	  if (!(test_level & G_LOG_FLAG_RECURSION) && !_g_debug_initialized)
	    {
443
	      GLogLevelFlags orig_test_level = test_level;
444 445 446 447 448 449 450 451 452 453 454 455 456 457

	      _g_debug_init ();
	      if ((domain_fatal_mask | g_log_always_fatal) & test_level)
		test_level |= G_LOG_FLAG_FATAL;
	      if (test_level != orig_test_level)
		{
		  /* need a relookup, not nice, but not too bad either */
		  g_mutex_lock (g_messages_lock);
		  domain = g_log_find_domain_L (log_domain ? log_domain : "");
		  log_func = g_log_domain_get_handler_L (domain, test_level, &data);
		  domain = NULL;
		  g_mutex_unlock (g_messages_lock);
		}
	    }
458

459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477
	  if (test_level & G_LOG_FLAG_RECURSION)
	    {
	      /* we use a stack buffer of fixed size, since we're likely
	       * in an out-of-memory situation
	       */
	      gchar buffer[1025];
	      gint size;
	      size = _g_vsnprintf (buffer, 1024, format, args1);

	      log_func (log_domain, test_level, buffer, data);
	    }
	  else
	    {
	      gchar *msg = g_strdup_vprintf (format, args1);

	      log_func (log_domain, test_level, msg, data);

	      g_free (msg);
	    }
478

479
	  if (test_level & G_LOG_FLAG_FATAL)
480
	    {
481
#ifdef G_OS_WIN32
482 483
	      gchar *locale_msg = g_locale_from_utf8 (fatal_msg_buf, -1, NULL, NULL, NULL);
	      
484 485
	      MessageBox (NULL, locale_msg, NULL,
			  MB_ICONERROR|MB_SETFOREGROUND);
486
	      if (IsDebuggerPresent () && !(test_level & G_LOG_FLAG_RECURSION))
487
		G_BREAKPOINT ();
488 489
	      else
		abort ();
490 491
#else
#if defined (G_ENABLE_DEBUG) && defined (SIGTRAP)
492
	      if (!(test_level & G_LOG_FLAG_RECURSION))
493
		G_BREAKPOINT ();
494 495
	      else
		abort ();
496
#else /* !G_ENABLE_DEBUG || !SIGTRAP */
497
	      abort ();
498 499
#endif /* !G_ENABLE_DEBUG || !SIGTRAP */
#endif /* !G_OS_WIN32 */
500
	    }
501
	  
502 503
	  depth--;
	  g_private_set (g_log_depth, GUINT_TO_POINTER (depth));
504
	}
Owen Taylor's avatar
Owen Taylor committed
505
    }
506 507 508
}

void
509 510 511
g_log (const gchar   *log_domain,
       GLogLevelFlags log_level,
       const gchar   *format,
512 513
       ...)
{
514
  va_list args;
515
  
516 517 518
  va_start (args, format);
  g_logv (log_domain, log_level, format, args);
  va_end (args);
519 520
}

521 522 523 524 525
void
g_return_if_fail_warning (const char *log_domain,
			  const char *pretty_function,
			  const char *expression)
{
526 527 528 529 530 531
  /*
   * Omit the prefix used by the PLT-reduction
   * technique used in GTK+. 
   */
  if (g_str_has_prefix (pretty_function, "IA__"))
    pretty_function += 4;
532 533 534 535
  g_log (log_domain,
	 G_LOG_LEVEL_CRITICAL,
	 "%s: assertion `%s' failed",
	 pretty_function,
Matthias Clasen's avatar
Matthias Clasen committed
536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559
	 expression);
}

void
g_assert_warning (const char *log_domain,
		  const char *file,
		  const int   line,
		  const char *pretty_function,
		  const char *expression)
{
  /*
   * Omit the prefix used by the PLT-reduction
   * technique used in GTK+. 
   */
  if (g_str_has_prefix (pretty_function, "IA__"))
    pretty_function += 4;
  g_log (log_domain,
	 G_LOG_LEVEL_ERROR,
	 expression 
	 ? "file %s: line %d (%s): assertion failed: (%s)"
	 : "file %s: line %d (%s): should not be reached",
	 file, 
	 line, 
	 pretty_function,
560
	 expression);
561
  abort ();
562 563
}

564 565 566 567
#define CHAR_IS_SAFE(wc) (!((wc < 0x20 && wc != '\t' && wc != '\n' && wc != '\r') || \
			    (wc == 0x7f) || \
			    (wc >= 0x80 && wc < 0xa0)))
     
568 569 570 571 572
static gchar*
strdup_convert (const gchar *string,
		const gchar *charset)
{
  if (!g_utf8_validate (string, -1, NULL))
573 574 575 576 577 578 579 580 581 582 583
    {
      GString *gstring = g_string_new ("[Invalid UTF-8] ");
      guchar *p;

      for (p = (guchar *)string; *p; p++)
	{
	  if (CHAR_IS_SAFE(*p) &&
	      !(*p == '\r' && *(p + 1) != '\n') &&
	      *p < 0x80)
	    g_string_append_c (gstring, *p);
	  else
584
	    g_string_append_printf (gstring, "\\x%02x", (guint)(guchar)*p);
585 586 587 588
	}
      
      return g_string_free (gstring, FALSE);
    }
589
  else
590 591 592 593 594 595 596 597 598 599 600 601 602 603
    {
      GError *err = NULL;
      
      gchar *result = g_convert_with_fallback (string, -1, charset, "UTF-8", "?", NULL, NULL, &err);
      if (result)
	return result;
      else
	{
	  /* Not thread-safe, but doesn't matter if we print the warning twice
	   */
	  static gboolean warned = FALSE; 
	  if (!warned)
	    {
	      warned = TRUE;
604
	      _g_fprintf (stderr, "GLib: Cannot convert message: %s\n", err->message);
605 606 607 608 609 610
	    }
	  g_error_free (err);
	  
	  return g_strdup (string);
	}
    }
611 612
}

613 614 615 616 617 618 619 620 621 622
/* For a radix of 8 we need at most 3 output bytes for 1 input
 * byte. Additionally we might need up to 2 output bytes for the
 * readix prefix and 1 byte for the trailing NULL.
 */
#define FORMAT_UNSIGNED_BUFSIZE ((GLIB_SIZEOF_LONG * 3) + 3)

static void
format_unsigned (gchar  *buf,
		 gulong  num,
		 guint   radix)
623
{
624 625 626 627 628 629 630 631 632 633 634
  gulong tmp;
  gchar c;
  gint i, n;

  /* we may not call _any_ GLib functions here (or macros like g_return_if_fail()) */

  if (radix != 8 && radix != 10 && radix != 16)
    {
      *buf = '\000';
      return;
    }
635
  
636 637 638 639 640 641
  if (!num)
    {
      *buf++ = '0';
      *buf = '\000';
      return;
    } 
642
  
643
  if (radix == 16)
Owen Taylor's avatar
Owen Taylor committed
644
    {
645 646 647 648 649 650 651 652 653 654 655 656 657 658 659
      *buf++ = '0';
      *buf++ = 'x';
    }
  else if (radix == 8)
    {
      *buf++ = '0';
    }
	
  n = 0;
  tmp = num;
  while (tmp)
    {
      tmp /= radix;
      n++;
    }
660

661 662 663 664 665 666 667 668 669 670 671 672 673 674 675
  i = n;

  /* Again we can't use g_assert; actually this check should _never_ fail. */
  if (n > FORMAT_UNSIGNED_BUFSIZE - 3)
    {
      *buf = '\000';
      return;
    }

  while (num)
    {
      i--;
      c = (num % radix);
      if (c < 10)
	buf[i] = c + '0';
676
      else
677 678 679 680 681 682 683 684 685 686 687 688
	buf[i] = c + 'a' - 10;
      num /= radix;
    }
  
  buf[n] = '\000';
}

/* string size big enough to hold level prefix */
#define	STRING_BUFFER_SIZE	(FORMAT_UNSIGNED_BUFSIZE + 32)

#define	ALERT_LEVELS		(G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING)

689
static int
690 691
mklevel_prefix (gchar          level_prefix[STRING_BUFFER_SIZE],
		GLogLevelFlags log_level)
692 693 694 695 696 697 698 699 700 701
{
  gboolean to_stdout = TRUE;

  /* we may not call _any_ GLib functions here */

  switch (log_level & G_LOG_LEVEL_MASK)
    {
    case G_LOG_LEVEL_ERROR:
      strcpy (level_prefix, "ERROR");
      to_stdout = FALSE;
702 703
      break;
    case G_LOG_LEVEL_CRITICAL:
704 705
      strcpy (level_prefix, "CRITICAL");
      to_stdout = FALSE;
706 707
      break;
    case G_LOG_LEVEL_WARNING:
708 709
      strcpy (level_prefix, "WARNING");
      to_stdout = FALSE;
710 711
      break;
    case G_LOG_LEVEL_MESSAGE:
712 713
      strcpy (level_prefix, "Message");
      to_stdout = FALSE;
714 715
      break;
    case G_LOG_LEVEL_INFO:
716 717 718 719 720 721 722
      strcpy (level_prefix, "INFO");
      break;
    case G_LOG_LEVEL_DEBUG:
      strcpy (level_prefix, "DEBUG");
      break;
    default:
      if (log_level)
723
	{
724 725
	  strcpy (level_prefix, "LOG-");
	  format_unsigned (level_prefix + 4, log_level & G_LOG_LEVEL_MASK, 16);
726 727
	}
      else
728
	strcpy (level_prefix, "LOG");
729
      break;
730 731 732 733 734
    }
  if (log_level & G_LOG_FLAG_RECURSION)
    strcat (level_prefix, " (recursed)");
  if (log_level & ALERT_LEVELS)
    strcat (level_prefix, " **");
735

736 737 738
#ifdef G_OS_WIN32
  win32_keep_fatal_message = (log_level & G_LOG_FLAG_FATAL) != 0;
#endif
739
  return to_stdout ? 1 : 2;
740
}
741

742 743 744 745 746 747
void
_g_log_fallback_handler (const gchar   *log_domain,
			 GLogLevelFlags log_level,
			 const gchar   *message,
			 gpointer       unused_data)
{
748 749 750 751
  gchar level_prefix[STRING_BUFFER_SIZE];
#ifndef G_OS_WIN32
  gchar pid_string[FORMAT_UNSIGNED_BUFSIZE];
#endif
752
  gboolean is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
753
  int fd;
754 755 756 757 758 759 760 761 762 763 764 765

  /* we can not call _any_ GLib functions in this fallback handler,
   * which is why we skip UTF-8 conversion, etc.
   * since we either recursed or ran out of memory, we're in a pretty
   * pathologic situation anyways, what we can do is giving the
   * the process ID unconditionally however.
   */

  fd = mklevel_prefix (level_prefix, log_level);
  if (!message)
    message = "(NULL) message";

766
#ifndef G_OS_WIN32
767
  format_unsigned (pid_string, getpid (), 10);
768
#endif
769 770 771 772 773

  if (log_domain)
    write_string (fd, "\n");
  else
    write_string (fd, "\n** ");
774 775

#ifndef G_OS_WIN32
776 777 778
  write_string (fd, "(process:");
  write_string (fd, pid_string);
  write_string (fd, "): ");
779 780
#endif

781 782 783 784 785 786 787 788 789 790 791 792 793 794
  if (log_domain)
    {
      write_string (fd, log_domain);
      write_string (fd, "-");
    }
  write_string (fd, level_prefix);
  write_string (fd, ": ");
  write_string (fd, message);
  if (is_fatal)
    write_string (fd, "\naborting...\n");
  else
    write_string (fd, "\n");
}

795 796 797 798 799 800 801 802 803 804
static void
escape_string (GString *string)
{
  const char *p = string->str;
  gunichar wc;

  while (p < string->str + string->len)
    {
      gboolean safe;
	    
805 806 807 808
      wc = g_utf8_get_char_validated (p, -1);
      if (wc == (gunichar)-1 || wc == (gunichar)-2)  
	{
	  gchar *tmp;
809 810 811 812
	  guint pos;

	  pos = p - string->str;

813 814 815
	  /* Emit invalid UTF-8 as hex escapes 
           */
	  tmp = g_strdup_printf ("\\x%02x", (guint)(guchar)*p);
816 817
	  g_string_erase (string, pos, 1);
	  g_string_insert (string, pos, tmp);
818

819
	  p = string->str + (pos + 4); /* Skip over escape sequence */
820

821
	  g_free (tmp);
822 823
	  continue;
	}
824 825 826 827 828 829 830 831 832 833 834 835
      if (wc == '\r')
	{
	  safe = *(p + 1) == '\n';
	}
      else
	{
	  safe = CHAR_IS_SAFE (wc);
	}
      
      if (!safe)
	{
	  gchar *tmp;
836 837 838
	  guint pos;

	  pos = p - string->str;
839 840 841 842 843
	  
	  /* Largest char we escape is 0x0a, so we don't have to worry
	   * about 8-digit \Uxxxxyyyy
	   */
	  tmp = g_strdup_printf ("\\u%04x", wc); 
844 845
	  g_string_erase (string, pos, g_utf8_next_char (p) - p);
	  g_string_insert (string, pos, tmp);
846 847
	  g_free (tmp);

848
	  p = string->str + (pos + 6); /* Skip over escape sequence */
849 850 851 852 853 854
	}
      else
	p = g_utf8_next_char (p);
    }
}

855 856 857 858 859 860 861 862 863
void
g_log_default_handler (const gchar   *log_domain,
		       GLogLevelFlags log_level,
		       const gchar   *message,
		       gpointer	      unused_data)
{
  gboolean is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
  gchar level_prefix[STRING_BUFFER_SIZE], *string;
  GString *gstring;
864
  int fd;
865 866 867 868 869 870 871 872 873 874 875 876

  /* we can be called externally with recursion for whatever reason */
  if (log_level & G_LOG_FLAG_RECURSION)
    {
      _g_log_fallback_handler (log_domain, log_level, message, unused_data);
      return;
    }

  g_messages_prefixed_init ();

  fd = mklevel_prefix (level_prefix, log_level);

877
  gstring = g_string_new (NULL);
878 879 880 881 882 883 884 885 886 887
  if (log_level & ALERT_LEVELS)
    g_string_append (gstring, "\n");
  if (!log_domain)
    g_string_append (gstring, "** ");

  if ((g_log_msg_prefix & log_level) == log_level)
    {
      const gchar *prg_name = g_get_prgname ();
      
      if (!prg_name)
888
	g_string_append_printf (gstring, "(process:%lu): ", (gulong)getpid ());
889
      else
890
	g_string_append_printf (gstring, "(%s:%lu): ", prg_name, (gulong)getpid ());
891
    }
892

893 894 895 896 897 898
  if (log_domain)
    {
      g_string_append (gstring, log_domain);
      g_string_append_c (gstring, '-');
    }
  g_string_append (gstring, level_prefix);
899

900 901 902 903 904
  g_string_append (gstring, ": ");
  if (!message)
    g_string_append (gstring, "(NULL) message");
  else
    {
905
      GString *msg;
906 907
      const gchar *charset;

908 909 910
      msg = g_string_new (message);
      escape_string (msg);

911
      if (g_get_charset (&charset))
912
	g_string_append (gstring, msg->str);	/* charset is UTF-8 already */
913 914
      else
	{
915
	  string = strdup_convert (msg->str, charset);
916 917
	  g_string_append (gstring, string);
	  g_free (string);
918
	}
919

920
      g_string_free (msg, TRUE);
Owen Taylor's avatar
Owen Taylor committed
921
    }
922 923 924 925 926 927 928 929 930
  if (is_fatal)
    g_string_append (gstring, "\naborting...\n");
  else
    g_string_append (gstring, "\n");

  string = g_string_free (gstring, FALSE);

  write_string (fd, string);
  g_free (string);
Owen Taylor's avatar
Owen Taylor committed
931 932
}

933 934 935 936 937
GPrintFunc
g_set_print_handler (GPrintFunc func)
{
  GPrintFunc old_print_func;
  
938
  g_mutex_lock (g_messages_lock);
939 940
  old_print_func = glib_print_func;
  glib_print_func = func;
941
  g_mutex_unlock (g_messages_lock);
942 943 944 945
  
  return old_print_func;
}

Owen Taylor's avatar
Owen Taylor committed
946
void
947 948
g_print (const gchar *format,
	 ...)
Owen Taylor's avatar
Owen Taylor committed
949
{
950 951
  va_list args;
  gchar *string;
952
  GPrintFunc local_glib_print_func;
953 954 955
  
  g_return_if_fail (format != NULL);
  
Owen Taylor's avatar
Owen Taylor committed
956
  va_start (args, format);
957
  string = g_strdup_vprintf (format, args);
Owen Taylor's avatar
Owen Taylor committed
958
  va_end (args);
959
  
960 961 962
  g_mutex_lock (g_messages_lock);
  local_glib_print_func = glib_print_func;
  g_mutex_unlock (g_messages_lock);
963
  
964 965
  if (local_glib_print_func)
    local_glib_print_func (string);
Owen Taylor's avatar
Owen Taylor committed
966 967
  else
    {
968 969 970 971 972 973 974 975 976 977 978
      const gchar *charset;

      if (g_get_charset (&charset))
	fputs (string, stdout); /* charset is UTF-8 already */
      else
	{
	  gchar *lstring = strdup_convert (string, charset);

	  fputs (lstring, stdout);
	  g_free (lstring);
	}
979
      fflush (stdout);
Owen Taylor's avatar
Owen Taylor committed
980
    }
981
  g_free (string);
Owen Taylor's avatar
Owen Taylor committed
982 983
}

984 985 986 987 988
GPrintFunc
g_set_printerr_handler (GPrintFunc func)
{
  GPrintFunc old_printerr_func;
  
989
  g_mutex_lock (g_messages_lock);
990 991
  old_printerr_func = glib_printerr_func;
  glib_printerr_func = func;
992
  g_mutex_unlock (g_messages_lock);
993 994 995 996
  
  return old_printerr_func;
}

Owen Taylor's avatar
Owen Taylor committed
997
void
998 999
g_printerr (const gchar *format,
	    ...)
Owen Taylor's avatar
Owen Taylor committed
1000
{
1001 1002
  va_list args;
  gchar *string;
1003
  GPrintFunc local_glib_printerr_func;
1004 1005 1006
  
  g_return_if_fail (format != NULL);
  
Owen Taylor's avatar
Owen Taylor committed
1007
  va_start (args, format);
1008
  string = g_strdup_vprintf (format, args);
Owen Taylor's avatar
Owen Taylor committed
1009
  va_end (args);
1010
  
1011 1012 1013
  g_mutex_lock (g_messages_lock);
  local_glib_printerr_func = glib_printerr_func;
  g_mutex_unlock (g_messages_lock);
1014
  
1015 1016
  if (local_glib_printerr_func)
    local_glib_printerr_func (string);
Owen Taylor's avatar
Owen Taylor committed
1017 1018
  else
    {
1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029
      const gchar *charset;

      if (g_get_charset (&charset))
	fputs (string, stderr); /* charset is UTF-8 already */
      else
	{
	  gchar *lstring = strdup_convert (string, charset);

	  fputs (lstring, stderr);
	  g_free (lstring);
	}
1030
      fflush (stderr);
Owen Taylor's avatar
Owen Taylor committed
1031
    }
1032
  g_free (string);
Owen Taylor's avatar
Owen Taylor committed
1033 1034
}

1035
gsize
1036 1037 1038
g_printf_string_upper_bound (const gchar *format,
			     va_list      args)
{
1039
  gchar c;
1040
  return _g_vsnprintf (&c, 1, format, args) + 1;
1041 1042
}

1043
void
1044
_g_messages_thread_init_nomessage (void)
1045
{
1046
  g_messages_lock = g_mutex_new ();
1047
  g_log_depth = g_private_new (NULL);
1048
  g_messages_prefixed_init ();
1049 1050 1051 1052 1053 1054
  _g_debug_init ();
}

gboolean _g_debug_initialized = FALSE;
guint _g_debug_flags = 0;

1055 1056
void
_g_debug_init (void) 
1057 1058 1059 1060
{
  const gchar *val;
  
  _g_debug_initialized = TRUE;
1061
  
1062 1063 1064
  val = g_getenv ("G_DEBUG");
  if (val != NULL)
    {
1065
      const GDebugKey keys[] = {
1066 1067
	{"fatal_warnings", G_DEBUG_FATAL_WARNINGS},
	{"fatal_criticals", G_DEBUG_FATAL_CRITICALS}
1068
      };
1069
      
1070 1071
      _g_debug_flags = g_parse_debug_string (val, keys, G_N_ELEMENTS (keys));
    }
1072
  
1073 1074 1075 1076 1077 1078 1079 1080
  if (_g_debug_flags & G_DEBUG_FATAL_WARNINGS) 
    {
      GLogLevelFlags fatal_mask;
      
      fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
      fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
      g_log_set_always_fatal (fatal_mask);
    }
1081 1082 1083 1084 1085 1086 1087 1088 1089
  
  if (_g_debug_flags & G_DEBUG_FATAL_CRITICALS) 
    {
      GLogLevelFlags fatal_mask;
      
      fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
      fatal_mask |= G_LOG_LEVEL_CRITICAL;
      g_log_set_always_fatal (fatal_mask);
    }
1090
}
1091 1092 1093

#define __G_MESSAGES_C__
#include "galiasdef.c"