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