00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifdef HAVE_CONFIG_H
00032 #include <config.h>
00033 #endif
00034
00035 #include <stdlib.h>
00036 #include <stdarg.h>
00037 #include <stdio.h>
00038 #include <string.h>
00039 #include "glib.h"
00040 #ifdef HAVE_UNISTD_H
00041 #include <unistd.h>
00042 #endif
00043
00044 #ifdef NATIVE_WIN32
00045 #define STRICT
00046 #include <windows.h>
00047
00048
00049 #undef write
00050
00051 static inline int
00052 write (FILE *fd,
00053 const char *buf,
00054 int len)
00055 {
00056 fwrite (buf, len, 1, fd);
00057
00058 return len;
00059 }
00060
00061 static void
00062 ensure_stdout_valid (void)
00063 {
00064 HANDLE handle;
00065
00066 handle = GetStdHandle (STD_OUTPUT_HANDLE);
00067
00068 if (handle == INVALID_HANDLE_VALUE)
00069 {
00070 AllocConsole ();
00071 freopen ("CONOUT$", "w", stdout);
00072 }
00073 }
00074 #else
00075 #define ensure_stdout_valid()
00076 #endif
00077
00078
00079
00080 typedef struct _GLogDomain GLogDomain;
00081 typedef struct _GLogHandler GLogHandler;
00082 struct _GLogDomain
00083 {
00084 gchar *log_domain;
00085 GLogLevelFlags fatal_mask;
00086 GLogHandler *handlers;
00087 GLogDomain *next;
00088 };
00089 struct _GLogHandler
00090 {
00091 guint id;
00092 GLogLevelFlags log_level;
00093 GLogFunc log_func;
00094 gpointer data;
00095 GLogHandler *next;
00096 };
00097
00098
00099
00100
00101 static GMutex* g_messages_lock = NULL;
00102
00103 const gchar *g_log_domain_glib = "GLib";
00104 static GLogDomain *g_log_domains = NULL;
00105 static GLogLevelFlags g_log_always_fatal = G_LOG_FATAL_MASK;
00106 static GPrintFunc glib_print_func = NULL;
00107 static GPrintFunc glib_printerr_func = NULL;
00108 static GErrorFunc glib_error_func = NULL;
00109 static GWarningFunc glib_warning_func = NULL;
00110 static GPrintFunc glib_message_func = NULL;
00111
00112 static GPrivate* g_log_depth = NULL;
00113
00114
00115
00116 static inline GLogDomain*
00117 g_log_find_domain (const gchar *log_domain)
00118 {
00119 register GLogDomain *domain;
00120
00121 g_mutex_lock (g_messages_lock);
00122 domain = g_log_domains;
00123 while (domain)
00124 {
00125 if (strcmp (domain->log_domain, log_domain) == 0)
00126 {
00127 g_mutex_unlock (g_messages_lock);
00128 return domain;
00129 }
00130 domain = domain->next;
00131 }
00132 g_mutex_unlock (g_messages_lock);
00133 return NULL;
00134 }
00135
00136 static inline GLogDomain*
00137 g_log_domain_new (const gchar *log_domain)
00138 {
00139 register GLogDomain *domain;
00140
00141 domain = g_new (GLogDomain, 1);
00142 domain->log_domain = g_strdup (log_domain);
00143 domain->fatal_mask = G_LOG_FATAL_MASK;
00144 domain->handlers = NULL;
00145
00146 g_mutex_lock (g_messages_lock);
00147 domain->next = g_log_domains;
00148 g_log_domains = domain;
00149 g_mutex_unlock (g_messages_lock);
00150
00151 return domain;
00152 }
00153
00154 static inline void
00155 g_log_domain_check_free (GLogDomain *domain)
00156 {
00157 if (domain->fatal_mask == G_LOG_FATAL_MASK &&
00158 domain->handlers == NULL)
00159 {
00160 register GLogDomain *last, *work;
00161
00162 last = NULL;
00163
00164 g_mutex_lock (g_messages_lock);
00165 work = g_log_domains;
00166 while (work)
00167 {
00168 if (work == domain)
00169 {
00170 if (last)
00171 last->next = domain->next;
00172 else
00173 g_log_domains = domain->next;
00174 g_free (domain->log_domain);
00175 g_free (domain);
00176 break;
00177 }
00178 last = work;
00179 work = last->next;
00180 }
00181 g_mutex_unlock (g_messages_lock);
00182 }
00183 }
00184
00185 static inline GLogFunc
00186 g_log_domain_get_handler (GLogDomain *domain,
00187 GLogLevelFlags log_level,
00188 gpointer *data)
00189 {
00190 if (domain && log_level)
00191 {
00192 register GLogHandler *handler;
00193
00194 handler = domain->handlers;
00195 while (handler)
00196 {
00197 if ((handler->log_level & log_level) == log_level)
00198 {
00199 *data = handler->data;
00200 return handler->log_func;
00201 }
00202 handler = handler->next;
00203 }
00204 }
00205 return g_log_default_handler;
00206 }
00207
00208 GLogLevelFlags
00209 g_log_set_always_fatal (GLogLevelFlags fatal_mask)
00210 {
00211 GLogLevelFlags old_mask;
00212
00213
00214 fatal_mask &= (1 << G_LOG_LEVEL_USER_SHIFT) - 1;
00215
00216 fatal_mask |= G_LOG_LEVEL_ERROR;
00217
00218 fatal_mask &= ~G_LOG_FLAG_FATAL;
00219
00220 g_mutex_lock (g_messages_lock);
00221 old_mask = g_log_always_fatal;
00222 g_log_always_fatal = fatal_mask;
00223 g_mutex_unlock (g_messages_lock);
00224
00225 return old_mask;
00226 }
00227
00228 GLogLevelFlags
00229 g_log_set_fatal_mask (const gchar *log_domain,
00230 GLogLevelFlags fatal_mask)
00231 {
00232 GLogLevelFlags old_flags;
00233 register GLogDomain *domain;
00234
00235 if (!log_domain)
00236 log_domain = "";
00237
00238
00239 fatal_mask |= G_LOG_LEVEL_ERROR;
00240
00241 fatal_mask &= ~G_LOG_FLAG_FATAL;
00242
00243 domain = g_log_find_domain (log_domain);
00244 if (!domain)
00245 domain = g_log_domain_new (log_domain);
00246 old_flags = domain->fatal_mask;
00247
00248 domain->fatal_mask = fatal_mask;
00249 g_log_domain_check_free (domain);
00250
00251 return old_flags;
00252 }
00253
00254 guint
00255 g_log_set_handler (const gchar *log_domain,
00256 GLogLevelFlags log_levels,
00257 GLogFunc log_func,
00258 gpointer user_data)
00259 {
00260 register GLogDomain *domain;
00261 register GLogHandler *handler;
00262 static guint handler_id = 0;
00263
00264 g_return_val_if_fail ((log_levels & G_LOG_LEVEL_MASK) != 0, 0);
00265 g_return_val_if_fail (log_func != NULL, 0);
00266
00267 if (!log_domain)
00268 log_domain = "";
00269
00270 domain = g_log_find_domain (log_domain);
00271 if (!domain)
00272 domain = g_log_domain_new (log_domain);
00273
00274 handler = g_new (GLogHandler, 1);
00275 g_mutex_lock (g_messages_lock);
00276 handler->id = ++handler_id;
00277 g_mutex_unlock (g_messages_lock);
00278 handler->log_level = log_levels;
00279 handler->log_func = log_func;
00280 handler->data = user_data;
00281 handler->next = domain->handlers;
00282 domain->handlers = handler;
00283
00284 return handler_id;
00285 }
00286
00287 void
00288 g_log_remove_handler (const gchar *log_domain,
00289 guint handler_id)
00290 {
00291 register GLogDomain *domain;
00292
00293 g_return_if_fail (handler_id > 0);
00294
00295 if (!log_domain)
00296 log_domain = "";
00297
00298 domain = g_log_find_domain (log_domain);
00299 if (domain)
00300 {
00301 register GLogHandler *work, *last;
00302
00303 last = NULL;
00304 work = domain->handlers;
00305 while (work)
00306 {
00307 if (work->id == handler_id)
00308 {
00309 if (last)
00310 last->next = work->next;
00311 else
00312 domain->handlers = work->next;
00313 g_free (work);
00314 g_log_domain_check_free (domain);
00315 return;
00316 }
00317 last = work;
00318 work = last->next;
00319 }
00320 }
00321 g_warning ("g_log_remove_handler(): could not find handler with id `%d' for domain \"%s\"",
00322 handler_id,
00323 log_domain);
00324 }
00325
00326 void
00327 g_logv (const gchar *log_domain,
00328 GLogLevelFlags log_level,
00329 const gchar *format,
00330 va_list args1)
00331 {
00332 va_list args2;
00333 gchar buffer[1025];
00334 register gint i;
00335
00336 log_level &= G_LOG_LEVEL_MASK;
00337 if (!log_level)
00338 return;
00339
00340
00341
00342
00343 G_VA_COPY (args2, args1);
00344 if (g_printf_string_upper_bound (format, args1) < 1024)
00345 vsprintf (buffer, format, args2);
00346 else
00347 {
00348
00349 #ifdef HAVE_VSNPRINTF
00350 vsnprintf (buffer, 1024, format, args2);
00351 #else
00352
00353 strncpy (buffer, format, 1024);
00354 #endif
00355 buffer[1024] = 0;
00356 }
00357 va_end (args2);
00358
00359 for (i = g_bit_nth_msf (log_level, -1); i >= 0; i = g_bit_nth_msf (log_level, i))
00360 {
00361 register GLogLevelFlags test_level;
00362
00363 test_level = 1 << i;
00364 if (log_level & test_level)
00365 {
00366 guint depth = GPOINTER_TO_UINT (g_private_get (g_log_depth));
00367 GLogDomain *domain;
00368 GLogFunc log_func;
00369 gpointer data = NULL;
00370
00371 domain = g_log_find_domain (log_domain ? log_domain : "");
00372
00373 if (depth)
00374 test_level |= G_LOG_FLAG_RECURSION;
00375
00376 depth++;
00377 g_private_set (g_log_depth, GUINT_TO_POINTER (depth));
00378
00379 g_mutex_lock (g_messages_lock);
00380 if ((((domain ? domain->fatal_mask : G_LOG_FATAL_MASK) |
00381 g_log_always_fatal) & test_level) != 0)
00382 test_level |= G_LOG_FLAG_FATAL;
00383 g_mutex_unlock (g_messages_lock);
00384
00385 log_func = g_log_domain_get_handler (domain, test_level, &data);
00386 log_func (log_domain, test_level, buffer, data);
00387
00388
00389
00390 if (test_level & G_LOG_FLAG_FATAL)
00391 abort ();
00392
00393 depth--;
00394 g_private_set (g_log_depth, GUINT_TO_POINTER (depth));
00395 }
00396 }
00397 }
00398
00399 void
00400 g_log (const gchar *log_domain,
00401 GLogLevelFlags log_level,
00402 const gchar *format,
00403 ...)
00404 {
00405 va_list args;
00406
00407 va_start (args, format);
00408 g_logv (log_domain, log_level, format, args);
00409 va_end (args);
00410 }
00411
00412 void
00413 g_log_default_handler (const gchar *log_domain,
00414 GLogLevelFlags log_level,
00415 const gchar *message,
00416 gpointer unused_data)
00417 {
00418 #ifdef NATIVE_WIN32
00419 FILE *fd;
00420 #else
00421 gint fd;
00422 #endif
00423 gboolean in_recursion;
00424 gboolean is_fatal;
00425 GErrorFunc local_glib_error_func;
00426 GWarningFunc local_glib_warning_func;
00427 GPrintFunc local_glib_message_func;
00428
00429 in_recursion = (log_level & G_LOG_FLAG_RECURSION) != 0;
00430 is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
00431 log_level &= G_LOG_LEVEL_MASK;
00432
00433 if (!message)
00434 message = "g_log_default_handler(): (NULL) message";
00435
00436 #ifdef NATIVE_WIN32
00437
00438
00439
00440 fd = stdout;
00441 #else
00442 fd = (log_level >= G_LOG_LEVEL_MESSAGE) ? 1 : 2;
00443 #endif
00444
00445 g_mutex_lock (g_messages_lock);
00446 local_glib_error_func = glib_error_func;
00447 local_glib_warning_func = glib_warning_func;
00448 local_glib_message_func = glib_message_func;
00449 g_mutex_unlock (g_messages_lock);
00450
00451 switch (log_level)
00452 {
00453 case G_LOG_LEVEL_ERROR:
00454 if (!log_domain && local_glib_error_func)
00455 {
00456
00457 local_glib_error_func (message);
00458 return;
00459 }
00460
00461 ensure_stdout_valid ();
00462 if (log_domain)
00463 {
00464 write (fd, "\n", 1);
00465 write (fd, log_domain, strlen (log_domain));
00466 write (fd, "-", 1);
00467 }
00468 else
00469 write (fd, "\n** ", 4);
00470 if (in_recursion)
00471 write (fd, "ERROR (recursed) **: ", 21);
00472 else
00473 write (fd, "ERROR **: ", 10);
00474 write (fd, message, strlen(message));
00475 if (is_fatal)
00476 write (fd, "\naborting...\n", 13);
00477 else
00478 write (fd, "\n", 1);
00479 break;
00480 case G_LOG_LEVEL_CRITICAL:
00481 ensure_stdout_valid ();
00482 if (log_domain)
00483 {
00484 write (fd, "\n", 1);
00485 write (fd, log_domain, strlen (log_domain));
00486 write (fd, "-", 1);
00487 }
00488 else
00489 write (fd, "\n** ", 4);
00490 if (in_recursion)
00491 write (fd, "CRITICAL (recursed) **: ", 24);
00492 else
00493 write (fd, "CRITICAL **: ", 13);
00494 write (fd, message, strlen(message));
00495 if (is_fatal)
00496 write (fd, "\naborting...\n", 13);
00497 else
00498 write (fd, "\n", 1);
00499 break;
00500 case G_LOG_LEVEL_WARNING:
00501 if (!log_domain && local_glib_warning_func)
00502 {
00503
00504 local_glib_warning_func (message);
00505 return;
00506 }
00507 ensure_stdout_valid ();
00508 if (log_domain)
00509 {
00510 write (fd, "\n", 1);
00511 write (fd, log_domain, strlen (log_domain));
00512 write (fd, "-", 1);
00513 }
00514 else
00515 write (fd, "\n** ", 4);
00516 if (in_recursion)
00517 write (fd, "WARNING (recursed) **: ", 23);
00518 else
00519 write (fd, "WARNING **: ", 12);
00520 write (fd, message, strlen(message));
00521 if (is_fatal)
00522 write (fd, "\naborting...\n", 13);
00523 else
00524 write (fd, "\n", 1);
00525 break;
00526 case G_LOG_LEVEL_MESSAGE:
00527 if (!log_domain && local_glib_message_func)
00528 {
00529
00530 local_glib_message_func (message);
00531 return;
00532 }
00533 ensure_stdout_valid ();
00534 if (log_domain)
00535 {
00536 write (fd, log_domain, strlen (log_domain));
00537 write (fd, "-", 1);
00538 }
00539 if (in_recursion)
00540 write (fd, "Message (recursed): ", 20);
00541 else
00542 write (fd, "Message: ", 9);
00543 write (fd, message, strlen(message));
00544 if (is_fatal)
00545 write (fd, "\naborting...\n", 13);
00546 else
00547 write (fd, "\n", 1);
00548 break;
00549 case G_LOG_LEVEL_INFO:
00550 ensure_stdout_valid ();
00551 if (log_domain)
00552 {
00553 write (fd, log_domain, strlen (log_domain));
00554 write (fd, "-", 1);
00555 }
00556 if (in_recursion)
00557 write (fd, "INFO (recursed): ", 17);
00558 else
00559 write (fd, "INFO: ", 6);
00560 write (fd, message, strlen(message));
00561 if (is_fatal)
00562 write (fd, "\naborting...\n", 13);
00563 else
00564 write (fd, "\n", 1);
00565 break;
00566 case G_LOG_LEVEL_DEBUG:
00567 ensure_stdout_valid ();
00568 if (log_domain)
00569 {
00570 write (fd, log_domain, strlen (log_domain));
00571 write (fd, "-", 1);
00572 }
00573 if (in_recursion)
00574 write (fd, "DEBUG (recursed): ", 18);
00575 else
00576 write (fd, "DEBUG: ", 7);
00577 write (fd, message, strlen(message));
00578 if (is_fatal)
00579 write (fd, "\naborting...\n", 13);
00580 else
00581 write (fd, "\n", 1);
00582 break;
00583 default:
00584
00585
00586
00587 ensure_stdout_valid ();
00588 if (log_domain)
00589 {
00590 write (fd, log_domain, strlen (log_domain));
00591 if (in_recursion)
00592 write (fd, "-LOG (recursed:", 15);
00593 else
00594 write (fd, "-LOG (", 6);
00595 }
00596 else if (in_recursion)
00597 write (fd, "LOG (recursed:", 14);
00598 else
00599 write (fd, "LOG (", 5);
00600 if (log_level)
00601 {
00602 gchar string[] = "0x00): ";
00603 gchar *p = string + 2;
00604 guint i;
00605
00606 i = g_bit_nth_msf (log_level, -1);
00607 *p = i >> 4;
00608 p++;
00609 *p = '0' + (i & 0xf);
00610 if (*p > '9')
00611 *p += 'A' - '9' - 1;
00612
00613 write (fd, string, 7);
00614 }
00615 else
00616 write (fd, "): ", 3);
00617 write (fd, message, strlen(message));
00618 if (is_fatal)
00619 write (fd, "\naborting...\n", 13);
00620 else
00621 write (fd, "\n", 1);
00622 break;
00623 }
00624 }
00625
00626 GPrintFunc
00627 g_set_print_handler (GPrintFunc func)
00628 {
00629 GPrintFunc old_print_func;
00630
00631 g_mutex_lock (g_messages_lock);
00632 old_print_func = glib_print_func;
00633 glib_print_func = func;
00634 g_mutex_unlock (g_messages_lock);
00635
00636 return old_print_func;
00637 }
00638
00639 void
00640 g_print (const gchar *format,
00641 ...)
00642 {
00643 va_list args;
00644 gchar *string;
00645 GPrintFunc local_glib_print_func;
00646
00647 g_return_if_fail (format != NULL);
00648
00649 va_start (args, format);
00650 string = g_strdup_vprintf (format, args);
00651 va_end (args);
00652
00653 g_mutex_lock (g_messages_lock);
00654 local_glib_print_func = glib_print_func;
00655 g_mutex_unlock (g_messages_lock);
00656
00657 if (local_glib_print_func)
00658 local_glib_print_func (string);
00659 else
00660 {
00661 ensure_stdout_valid ();
00662 fputs (string, stdout);
00663 fflush (stdout);
00664 }
00665 g_free (string);
00666 }
00667
00668 GPrintFunc
00669 g_set_printerr_handler (GPrintFunc func)
00670 {
00671 GPrintFunc old_printerr_func;
00672
00673 g_mutex_lock (g_messages_lock);
00674 old_printerr_func = glib_printerr_func;
00675 glib_printerr_func = func;
00676 g_mutex_unlock (g_messages_lock);
00677
00678 return old_printerr_func;
00679 }
00680
00681 void
00682 g_printerr (const gchar *format,
00683 ...)
00684 {
00685 va_list args;
00686 gchar *string;
00687 GPrintFunc local_glib_printerr_func;
00688
00689 g_return_if_fail (format != NULL);
00690
00691 va_start (args, format);
00692 string = g_strdup_vprintf (format, args);
00693 va_end (args);
00694
00695 g_mutex_lock (g_messages_lock);
00696 local_glib_printerr_func = glib_printerr_func;
00697 g_mutex_unlock (g_messages_lock);
00698
00699 if (local_glib_printerr_func)
00700 local_glib_printerr_func (string);
00701 else
00702 {
00703 fputs (string, stderr);
00704 fflush (stderr);
00705 }
00706 g_free (string);
00707 }
00708
00709
00710 GErrorFunc
00711 g_set_error_handler (GErrorFunc func)
00712 {
00713 GErrorFunc old_error_func;
00714
00715 g_mutex_lock (g_messages_lock);
00716 old_error_func = glib_error_func;
00717 glib_error_func = func;
00718 g_mutex_unlock (g_messages_lock);
00719
00720 return old_error_func;
00721 }
00722
00723
00724 GWarningFunc
00725 g_set_warning_handler (GWarningFunc func)
00726 {
00727 GWarningFunc old_warning_func;
00728
00729 g_mutex_lock (g_messages_lock);
00730 old_warning_func = glib_warning_func;
00731 glib_warning_func = func;
00732 g_mutex_unlock (g_messages_lock);
00733
00734 return old_warning_func;
00735 }
00736
00737
00738 GPrintFunc
00739 g_set_message_handler (GPrintFunc func)
00740 {
00741 GPrintFunc old_message_func;
00742
00743 g_mutex_lock (g_messages_lock);
00744 old_message_func = glib_message_func;
00745 glib_message_func = func;
00746 g_mutex_unlock (g_messages_lock);
00747
00748 return old_message_func;
00749 }
00750
00751 void
00752 g_messages_init (void)
00753 {
00754 g_messages_lock = g_mutex_new();
00755 g_log_depth = g_private_new(NULL);
00756 }