#include "glib.h"
#include "gdebug.h"
#include "gprintfint.h"
-#include "gthreadinit.h"
+#include "gthreadprivate.h"
+#include "galias.h"
#ifdef G_OS_WIN32
+#include <process.h> /* For getpid() */
#include <io.h>
-typedef FILE* GFileDescriptor;
-#else
-typedef gint GFileDescriptor;
+# define STRICT /* Strict typing, please */
+# define _WIN32_WINDOWS 0x0401 /* to get IsDebuggerPresent */
+# include <windows.h>
+# undef STRICT
#endif
/* --- structures --- */
static GPrintFunc glib_printerr_func = NULL;
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;
-
+static GLogFunc default_log_func = g_log_default_handler;
+static gpointer default_log_data = NULL;
/* --- functions --- */
#ifdef G_OS_WIN32
# define STRICT
# include <windows.h>
# undef STRICT
-# include <process.h> /* For _getpid() */
static gboolean win32_keep_fatal_message = FALSE;
/* This default message will usually be overwritten. */
-/* Yes, a fixed size buffer is bad. So sue me. But g_error is never
- * with huge strings, is it?
+/* Yes, a fixed size buffer is bad. So sue me. But g_error() is never
+ * called with huge strings, is it?
*/
static gchar fatal_msg_buf[1000] = "Unspecified fatal error encountered, aborting.";
static gchar *fatal_msg_ptr = fatal_msg_buf;
-/* Just use stdio. If we're out of memory, we're hosed anyway. */
#undef write
static inline int
-dowrite (GFileDescriptor fd,
+dowrite (int fd,
const void *buf,
unsigned int len)
{
return len;
}
- fwrite (buf, len, 1, fd);
- fflush (fd);
+ write (fd, buf, len);
return len;
}
#define write(fd, buf, len) dowrite(fd, buf, len)
-static void
-ensure_stdout_valid (void)
-{
- static gboolean alloc_console_called = FALSE;
- HANDLE handle;
-
- if (win32_keep_fatal_message)
- return;
-
- if (!alloc_console_called)
- {
- handle = (HANDLE) _get_osfhandle (fileno (stdout));
-
- if (handle == INVALID_HANDLE_VALUE)
- {
- AllocConsole ();
- alloc_console_called = TRUE;
- freopen ("CONOUT$", "w", stdout);
- }
- }
-}
-
-static void
-ensure_stderr_valid (void)
-{
- static gboolean alloc_console_called = FALSE;
- HANDLE handle;
-
- if (win32_keep_fatal_message)
- return;
-
- if (!alloc_console_called)
- {
- handle = (HANDLE) _get_osfhandle (fileno (stderr));
-
- if (handle == INVALID_HANDLE_VALUE)
- {
- AllocConsole ();
- alloc_console_called = TRUE;
- freopen ("CONOUT$", "w", stderr);
- }
- }
-}
-
-#else
-#define ensure_stdout_valid() /* Define as empty */
-#define ensure_stderr_valid()
#endif
static void
-write_string (GFileDescriptor fd,
- const gchar *string)
+write_string (int fd,
+ const gchar *string)
{
write (fd, string, strlen (string));
}
if (val)
{
- static const GDebugKey keys[] = {
+ const GDebugKey keys[] = {
{ "error", G_LOG_LEVEL_ERROR },
{ "critical", G_LOG_LEVEL_CRITICAL },
{ "warning", G_LOG_LEVEL_WARNING },
handler = handler->next;
}
}
- return g_log_default_handler;
+
+ *data = default_log_data;
+ return default_log_func;
}
GLogLevelFlags
return handler_id;
}
+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;
+}
+
void
g_log_remove_handler (const gchar *log_domain,
guint handler_id)
guint depth = GPOINTER_TO_UINT (g_private_get (g_log_depth));
GLogDomain *domain;
GLogFunc log_func;
- guint domain_fatal_mask;
+ GLogLevelFlags domain_fatal_mask;
gpointer data = NULL;
if (was_fatal)
/* had to defer debug initialization until we can keep track of recursion */
if (!(test_level & G_LOG_FLAG_RECURSION) && !_g_debug_initialized)
{
- guint orig_test_level = test_level;
+ GLogLevelFlags orig_test_level = test_level;
_g_debug_init ();
if ((domain_fatal_mask | g_log_always_fatal) & test_level)
MessageBox (NULL, locale_msg, NULL,
MB_ICONERROR|MB_SETFOREGROUND);
-#endif
-#if defined (G_ENABLE_DEBUG) && (defined (SIGTRAP) || defined (G_OS_WIN32))
+ if (IsDebuggerPresent () && !(test_level & G_LOG_FLAG_RECURSION))
+ G_BREAKPOINT ();
+ else
+ abort ();
+#else
+#if defined (G_ENABLE_DEBUG) && defined (SIGTRAP)
if (!(test_level & G_LOG_FLAG_RECURSION))
G_BREAKPOINT ();
else
abort ();
-#else /* !G_ENABLE_DEBUG || !(SIGTRAP || G_OS_WIN32) */
+#else /* !G_ENABLE_DEBUG || !SIGTRAP */
abort ();
-#endif /* !G_ENABLE_DEBUG || !(SIGTRAP || G_OS_WIN32) */
+#endif /* !G_ENABLE_DEBUG || !SIGTRAP */
+#endif /* !G_OS_WIN32 */
}
depth--;
va_end (args);
}
+void
+g_return_if_fail_warning (const char *log_domain,
+ 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_CRITICAL,
+ "%s: assertion `%s' failed",
+ pretty_function,
+ expression);
+}
+
+void
+g_warn_message (const char *domain,
+ const char *file,
+ int line,
+ const char *func,
+ const char *warnexpr)
+{
+ char *s, lstr[32];
+ g_snprintf (lstr, 32, "%d", line);
+ if (warnexpr)
+ s = g_strconcat ("(", file, ":", lstr, "):",
+ func, func[0] ? ":" : "",
+ " runtime check failed: (", warnexpr, ")", NULL);
+ else
+ s = g_strconcat ("(", file, ":", lstr, "):",
+ func, func[0] ? ":" : "",
+ " ", "code should not be reached", NULL);
+ g_log (domain, G_LOG_LEVEL_WARNING, "%s", s);
+ g_free (s);
+}
+
+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,
+ expression);
+ abort ();
+}
+
#define CHAR_IS_SAFE(wc) (!((wc < 0x20 && wc != '\t' && wc != '\n' && wc != '\r') || \
(wc == 0x7f) || \
(wc >= 0x80 && wc < 0xa0)))
*p < 0x80)
g_string_append_c (gstring, *p);
else
- g_string_append_printf (gstring, "\\%03o", *p);
+ g_string_append_printf (gstring, "\\x%02x", (guint)(guchar)*p);
}
return g_string_free (gstring, FALSE);
if (!warned)
{
warned = TRUE;
- ensure_stderr_valid ();
_g_fprintf (stderr, "GLib: Cannot convert message: %s\n", err->message);
}
g_error_free (err);
#define ALERT_LEVELS (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING)
-static GFileDescriptor
-mklevel_prefix (gchar level_prefix[STRING_BUFFER_SIZE],
- guint log_level)
+static int
+mklevel_prefix (gchar level_prefix[STRING_BUFFER_SIZE],
+ GLogLevelFlags log_level)
{
gboolean to_stdout = TRUE;
#ifdef G_OS_WIN32
win32_keep_fatal_message = (log_level & G_LOG_FLAG_FATAL) != 0;
-
- if (to_stdout)
- {
- ensure_stdout_valid ();
- return stdout;
- }
- else
- {
- ensure_stderr_valid ();
- return stderr;
- }
-#else
- return to_stdout ? 1 : 2;
#endif
+ return to_stdout ? 1 : 2;
}
void
const gchar *message,
gpointer unused_data)
{
- gchar level_prefix[STRING_BUFFER_SIZE], pid_string[FORMAT_UNSIGNED_BUFSIZE];
+ gchar level_prefix[STRING_BUFFER_SIZE];
+#ifndef G_OS_WIN32
+ gchar pid_string[FORMAT_UNSIGNED_BUFSIZE];
+#endif
gboolean is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
- GFileDescriptor fd;
+ int fd;
/* we can not call _any_ GLib functions in this fallback handler,
* which is why we skip UTF-8 conversion, etc.
if (!message)
message = "(NULL) message";
+#ifndef G_OS_WIN32
format_unsigned (pid_string, getpid (), 10);
+#endif
if (log_domain)
write_string (fd, "\n");
else
write_string (fd, "\n** ");
+
+#ifndef G_OS_WIN32
write_string (fd, "(process:");
write_string (fd, pid_string);
write_string (fd, "): ");
+#endif
+
if (log_domain)
{
write_string (fd, log_domain);
{
gboolean safe;
- wc = g_utf8_get_char (p);
+ wc = g_utf8_get_char_validated (p, -1);
+ if (wc == (gunichar)-1 || wc == (gunichar)-2)
+ {
+ gchar *tmp;
+ guint pos;
+
+ pos = p - string->str;
+
+ /* Emit invalid UTF-8 as hex escapes
+ */
+ tmp = g_strdup_printf ("\\x%02x", (guint)(guchar)*p);
+ g_string_erase (string, pos, 1);
+ g_string_insert (string, pos, tmp);
+
+ p = string->str + (pos + 4); /* Skip over escape sequence */
+
+ g_free (tmp);
+ continue;
+ }
if (wc == '\r')
{
safe = *(p + 1) == '\n';
if (!safe)
{
gchar *tmp;
+ guint pos;
+
+ pos = p - string->str;
- g_string_erase (string, p - string->str, g_utf8_next_char (p) - p);
/* Largest char we escape is 0x0a, so we don't have to worry
* about 8-digit \Uxxxxyyyy
*/
tmp = g_strdup_printf ("\\u%04x", wc);
- g_string_insert (string, p - string->str, tmp);
+ g_string_erase (string, pos, g_utf8_next_char (p) - p);
+ g_string_insert (string, pos, tmp);
g_free (tmp);
- p += 6; /* Skip over escape sequence */
+ p = string->str + (pos + 6); /* Skip over escape sequence */
}
else
p = g_utf8_next_char (p);
gboolean is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
gchar level_prefix[STRING_BUFFER_SIZE], *string;
GString *gstring;
- GFileDescriptor fd;
+ int fd;
/* we can be called externally with recursion for whatever reason */
if (log_level & G_LOG_FLAG_RECURSION)
g_string_append (gstring, "(NULL) message");
else
{
+ GString *msg;
const gchar *charset;
+ msg = g_string_new (message);
+ escape_string (msg);
+
if (g_get_charset (&charset))
- g_string_append (gstring, message); /* charset is UTF-8 already */
+ g_string_append (gstring, msg->str); /* charset is UTF-8 already */
else
{
- string = strdup_convert (message, charset);
+ string = strdup_convert (msg->str, charset);
g_string_append (gstring, string);
g_free (string);
}
- escape_string (gstring);
+ g_string_free (msg, TRUE);
}
if (is_fatal)
g_string_append (gstring, "\naborting...\n");
{
const gchar *charset;
- ensure_stdout_valid ();
if (g_get_charset (&charset))
fputs (string, stdout); /* charset is UTF-8 already */
else
{
const gchar *charset;
- ensure_stderr_valid ();
if (g_get_charset (&charset))
fputs (string, stderr); /* charset is UTF-8 already */
else
}
void
-_g_messages_thread_init (void)
+_g_messages_thread_init_nomessage (void)
{
g_messages_lock = g_mutex_new ();
+ g_log_depth = g_private_new (NULL);
g_messages_prefixed_init ();
_g_debug_init ();
}
-void
-_g_messages_thread_private_init (void)
-{
- g_assert (g_log_depth == NULL);
- g_log_depth = g_private_new (NULL);
-}
-
gboolean _g_debug_initialized = FALSE;
guint _g_debug_flags = 0;
val = g_getenv ("G_DEBUG");
if (val != NULL)
{
- static const GDebugKey keys[] = {
- {"fatal_warnings", G_DEBUG_FATAL_WARNINGS}
+ const GDebugKey keys[] = {
+ {"fatal_warnings", G_DEBUG_FATAL_WARNINGS},
+ {"fatal_criticals", G_DEBUG_FATAL_CRITICALS}
};
_g_debug_flags = g_parse_debug_string (val, keys, G_N_ELEMENTS (keys));
fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
g_log_set_always_fatal (fatal_mask);
}
+
+ 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);
+ }
}
+
+#define __G_MESSAGES_C__
+#include "galiasdef.c"