in case we have to abort the program, debugging is enabled and we are not
[platform/upstream/glib.git] / gmessages.c
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GLib Team and others 1997-1999.  See the AUTHORS
22  * file for a list of people on the GLib Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 /* 
28  * MT safe
29  */
30
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34
35 #include <stdlib.h>
36 #include <stdarg.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include "glib.h"
40 #ifdef HAVE_UNISTD_H
41 #include <unistd.h>
42 #endif
43 #include <signal.h>
44
45 #ifdef NATIVE_WIN32
46 #  define STRICT
47 #  include <windows.h>
48 #  include <process.h>          /* For _getpid() */
49
50 /* Just use stdio. If we're out of memory, we're hosed anyway. */
51 #undef write
52
53 static inline int
54 write (FILE       *fd,
55        const char *buf,
56        int         len)
57 {
58   fwrite (buf, len, 1, fd);
59
60   return len;
61 }
62
63 static void
64 ensure_stdout_valid (void)
65 {
66   HANDLE handle;
67
68   handle = GetStdHandle (STD_OUTPUT_HANDLE);
69   
70   if (handle == INVALID_HANDLE_VALUE)
71     {
72       AllocConsole ();
73       freopen ("CONOUT$", "w", stdout);
74     }
75 }
76 #else
77 #define ensure_stdout_valid()   /* Define as empty */
78 #endif
79         
80
81 /* --- structures --- */
82 typedef struct _GLogDomain      GLogDomain;
83 typedef struct _GLogHandler     GLogHandler;
84 struct _GLogDomain
85 {
86   gchar         *log_domain;
87   GLogLevelFlags fatal_mask;
88   GLogHandler   *handlers;
89   GLogDomain    *next;
90 };
91 struct _GLogHandler
92 {
93   guint          id;
94   GLogLevelFlags log_level;
95   GLogFunc       log_func;
96   gpointer       data;
97   GLogHandler   *next;
98 };
99
100
101 /* --- variables --- */
102
103 static GMutex* g_messages_lock = NULL;
104
105 const gchar          *g_log_domain_glib = "GLib";
106 static GLogDomain    *g_log_domains = NULL;
107 static GLogLevelFlags g_log_always_fatal = G_LOG_FATAL_MASK;
108 static GPrintFunc     glib_print_func = NULL;
109 static GPrintFunc     glib_printerr_func = NULL;
110 static GErrorFunc     glib_error_func = NULL;
111 static GWarningFunc   glib_warning_func = NULL;
112 static GPrintFunc     glib_message_func = NULL;
113
114 static GPrivate* g_log_depth = NULL;
115
116
117 /* --- functions --- */
118 static inline GLogDomain*
119 g_log_find_domain (const gchar    *log_domain)
120 {
121   register GLogDomain *domain;
122   
123   g_mutex_lock (g_messages_lock);
124   domain = g_log_domains;
125   while (domain)
126     {
127       if (strcmp (domain->log_domain, log_domain) == 0)
128         {
129           g_mutex_unlock (g_messages_lock);
130           return domain;
131         }
132       domain = domain->next;
133     }
134   g_mutex_unlock (g_messages_lock);
135   return NULL;
136 }
137
138 static inline GLogDomain*
139 g_log_domain_new (const gchar *log_domain)
140 {
141   register GLogDomain *domain;
142
143   domain = g_new (GLogDomain, 1);
144   domain->log_domain = g_strdup (log_domain);
145   domain->fatal_mask = G_LOG_FATAL_MASK;
146   domain->handlers = NULL;
147   
148   g_mutex_lock (g_messages_lock);
149   domain->next = g_log_domains;
150   g_log_domains = domain;
151   g_mutex_unlock (g_messages_lock);
152   
153   return domain;
154 }
155
156 static inline void
157 g_log_domain_check_free (GLogDomain *domain)
158 {
159   if (domain->fatal_mask == G_LOG_FATAL_MASK &&
160       domain->handlers == NULL)
161     {
162       register GLogDomain *last, *work;
163       
164       last = NULL;  
165
166       g_mutex_lock (g_messages_lock);
167       work = g_log_domains;
168       while (work)
169         {
170           if (work == domain)
171             {
172               if (last)
173                 last->next = domain->next;
174               else
175                 g_log_domains = domain->next;
176               g_free (domain->log_domain);
177               g_free (domain);
178               break;
179             }
180           work = work->next;
181         }  
182       g_mutex_unlock (g_messages_lock);
183     }
184 }
185
186 static inline GLogFunc
187 g_log_domain_get_handler (GLogDomain    *domain,
188                           GLogLevelFlags log_level,
189                           gpointer      *data)
190 {
191   if (domain && log_level)
192     {
193       register GLogHandler *handler;
194       
195       handler = domain->handlers;
196       while (handler)
197         {
198           if ((handler->log_level & log_level) == log_level)
199             {
200               *data = handler->data;
201               return handler->log_func;
202             }
203           handler = handler->next;
204         }
205     }
206   return g_log_default_handler;
207 }
208
209 GLogLevelFlags
210 g_log_set_always_fatal (GLogLevelFlags fatal_mask)
211 {
212   GLogLevelFlags old_mask;
213
214   /* restrict the global mask to levels that are known to glib */
215   fatal_mask &= (1 << G_LOG_LEVEL_USER_SHIFT) - 1;
216   /* force errors to be fatal */
217   fatal_mask |= G_LOG_LEVEL_ERROR;
218   /* remove bogus flag */
219   fatal_mask &= ~G_LOG_FLAG_FATAL;
220
221   g_mutex_lock (g_messages_lock);
222   old_mask = g_log_always_fatal;
223   g_log_always_fatal = fatal_mask;
224   g_mutex_unlock (g_messages_lock);
225
226   return old_mask;
227 }
228
229 GLogLevelFlags
230 g_log_set_fatal_mask (const gchar    *log_domain,
231                       GLogLevelFlags  fatal_mask)
232 {
233   GLogLevelFlags old_flags;
234   register GLogDomain *domain;
235   
236   if (!log_domain)
237     log_domain = "";
238   
239   /* force errors to be fatal */
240   fatal_mask |= G_LOG_LEVEL_ERROR;
241   /* remove bogus flag */
242   fatal_mask &= ~G_LOG_FLAG_FATAL;
243   
244   domain = g_log_find_domain (log_domain);
245   if (!domain)
246     domain = g_log_domain_new (log_domain);
247   old_flags = domain->fatal_mask;
248   
249   domain->fatal_mask = fatal_mask;
250   g_log_domain_check_free (domain);
251   
252   return old_flags;
253 }
254
255 guint
256 g_log_set_handler (const gchar    *log_domain,
257                    GLogLevelFlags  log_levels,
258                    GLogFunc        log_func,
259                    gpointer        user_data)
260 {
261   register GLogDomain *domain;
262   register GLogHandler *handler;
263   static guint handler_id = 0;
264   
265   g_return_val_if_fail ((log_levels & G_LOG_LEVEL_MASK) != 0, 0);
266   g_return_val_if_fail (log_func != NULL, 0);
267   
268   if (!log_domain)
269     log_domain = "";
270   
271   domain = g_log_find_domain (log_domain);
272   if (!domain)
273     domain = g_log_domain_new (log_domain);
274   
275   handler = g_new (GLogHandler, 1);
276   g_mutex_lock (g_messages_lock);
277   handler->id = ++handler_id;
278   g_mutex_unlock (g_messages_lock);
279   handler->log_level = log_levels;
280   handler->log_func = log_func;
281   handler->data = user_data;
282   handler->next = domain->handlers;
283   domain->handlers = handler;
284   
285   return handler_id;
286 }
287
288 void
289 g_log_remove_handler (const gchar    *log_domain,
290                       guint           handler_id)
291 {
292   register GLogDomain *domain;
293   
294   g_return_if_fail (handler_id > 0);
295   
296   if (!log_domain)
297     log_domain = "";
298   
299   domain = g_log_find_domain (log_domain);
300   if (domain)
301     {
302       register GLogHandler *work, *last;
303       
304       last = NULL;
305       work = domain->handlers;
306       while (work)
307         {
308           if (work->id == handler_id)
309             {
310               if (last)
311                 last->next = work->next;
312               else
313                 domain->handlers = work->next;
314               g_free (work);
315               g_log_domain_check_free (domain);
316               return;
317             }
318           work = work->next;
319         }
320     }
321   g_warning ("g_log_remove_handler(): could not find handler with id `%d' for domain \"%s\"",
322              handler_id,
323              log_domain);
324 }
325
326 void
327 g_logv (const gchar    *log_domain,
328         GLogLevelFlags  log_level,
329         const gchar    *format,
330         va_list         args1)
331 {
332   va_list args2;
333   gchar buffer[1025];
334   register gint i;
335   
336   log_level &= G_LOG_LEVEL_MASK;
337   if (!log_level)
338     return;
339   
340   /* we use a stack buffer of fixed size, because we might get called
341    * recursively.
342    */
343   G_VA_COPY (args2, args1);
344   if (g_printf_string_upper_bound (format, args1) < 1024)
345     vsprintf (buffer, format, args2);
346   else
347     {
348       /* since we might be out of memory, we can't use g_vsnprintf(). */
349 #ifdef  HAVE_VSNPRINTF
350       vsnprintf (buffer, 1024, format, args2);
351 #else   /* !HAVE_VSNPRINTF */
352       /* we are out of luck here */
353       strncpy (buffer, format, 1024);
354 #endif  /* !HAVE_VSNPRINTF */
355       buffer[1024] = 0;
356     }
357   va_end (args2);
358   
359   for (i = g_bit_nth_msf (log_level, -1); i >= 0; i = g_bit_nth_msf (log_level, i))
360     {
361       register GLogLevelFlags test_level;
362       
363       test_level = 1 << i;
364       if (log_level & test_level)
365         {
366           guint depth = GPOINTER_TO_UINT (g_private_get (g_log_depth));
367           GLogDomain *domain;
368           GLogFunc log_func;
369           gpointer data = NULL;
370           
371           domain = g_log_find_domain (log_domain ? log_domain : "");
372           
373           if (depth)
374             test_level |= G_LOG_FLAG_RECURSION;
375           
376           depth++;
377           g_private_set (g_log_depth, GUINT_TO_POINTER (depth));
378
379           g_mutex_lock (g_messages_lock);
380           if ((((domain ? domain->fatal_mask : G_LOG_FATAL_MASK) | 
381                 g_log_always_fatal) & test_level) != 0)
382             test_level |= G_LOG_FLAG_FATAL;  
383           g_mutex_unlock (g_messages_lock);
384
385           log_func = g_log_domain_get_handler (domain, test_level, &data);
386           log_func (log_domain, test_level, buffer, data);
387           
388           /* *domain can be cluttered now */
389           
390           if (test_level & G_LOG_FLAG_FATAL)
391             {
392 #if defined (G_ENABLE_DEBUG) && defined (SIGTRAP)
393               if (!(test_level & G_LOG_FLAG_RECURSION))
394                 raise (SIGTRAP);
395               else
396                 abort ();
397 #else /* !G_ENABLE_DEBUG || !SIGTRAP */
398               abort ();
399 #endif /* !G_ENABLE_DEBUG || !SIGTRAP */
400             }
401           
402           depth--;
403           g_private_set (g_log_depth, GUINT_TO_POINTER (depth));
404         }
405     }
406 }
407
408 void
409 g_log (const gchar    *log_domain,
410        GLogLevelFlags  log_level,
411        const gchar    *format,
412        ...)
413 {
414   va_list args;
415   
416   va_start (args, format);
417   g_logv (log_domain, log_level, format, args);
418   va_end (args);
419 }
420
421 void
422 g_log_default_handler (const gchar    *log_domain,
423                        GLogLevelFlags  log_level,
424                        const gchar    *message,
425                        gpointer        unused_data)
426 {
427 #ifdef NATIVE_WIN32
428   FILE *fd;
429 #else
430   gint fd;
431 #endif
432   gboolean in_recursion;
433   gboolean is_fatal;  
434   GErrorFunc local_glib_error_func;
435   GWarningFunc local_glib_warning_func;
436   GPrintFunc local_glib_message_func;
437   gchar prg_pid[64], *prg_name = g_get_prgname ();
438
439   in_recursion = (log_level & G_LOG_FLAG_RECURSION) != 0;
440   is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
441   log_level &= G_LOG_LEVEL_MASK;
442   
443   if (!message)
444     message = "g_log_default_handler(): (NULL) message";
445   if (!prg_name)
446     {
447       prg_name = "(process";
448       sprintf (prg_pid, ":%u): ", getpid ());
449     }
450   else
451     sprintf (prg_pid, " (pid:%u): ", getpid ());
452   
453 #ifdef NATIVE_WIN32
454   /* Use just stdout as stderr is hard to get redirected from the
455    * DOS prompt.
456    */
457   fd = stdout;
458 #else
459   fd = (log_level >= G_LOG_LEVEL_MESSAGE) ? 1 : 2;
460 #endif
461   
462   g_mutex_lock (g_messages_lock);
463   local_glib_error_func = glib_error_func;
464   local_glib_warning_func = glib_warning_func;
465   local_glib_message_func = glib_message_func;
466   g_mutex_unlock (g_messages_lock);
467
468   switch (log_level)
469     {
470     case G_LOG_LEVEL_ERROR:
471       if (!log_domain && local_glib_error_func)
472         {
473           /* compatibility code */
474           local_glib_error_func (message);  
475           return;
476         }
477       /* use write(2) for output, in case we are out of memeory */
478       ensure_stdout_valid ();
479       write (fd, "\n", 1);
480 #ifdef G_ENABLE_MSG_PREFIX
481       write (fd, prg_name, strlen (prg_name));
482       write (fd, prg_pid, strlen (prg_pid));
483 #endif /* G_ENABLE_MSG_PREFIX */
484       if (log_domain)
485         {
486           write (fd, log_domain, strlen (log_domain));
487           write (fd, "-", 1);
488         }
489       else
490         write (fd, "** ", 3);
491       if (in_recursion)
492         write (fd, "ERROR (recursed) **: ", 21);
493       else
494         write (fd, "ERROR **: ", 10);
495       write (fd, message, strlen (message));
496       if (is_fatal)
497         write (fd, "\naborting...\n", 13);
498       else
499         write (fd, "\n", 1);
500       break;
501     case G_LOG_LEVEL_CRITICAL:
502       ensure_stdout_valid ();
503       write (fd, "\n", 1);
504 #ifdef G_ENABLE_MSG_PREFIX
505       write (fd, prg_name, strlen (prg_name));
506       write (fd, prg_pid, strlen (prg_pid));
507 #endif /* G_ENABLE_MSG_PREFIX */
508       if (log_domain)
509         {
510           write (fd, log_domain, strlen (log_domain));
511           write (fd, "-", 1);
512         }
513       else
514         write (fd, "** ", 3);
515       if (in_recursion)
516         write (fd, "CRITICAL (recursed) **: ", 24);
517       else
518         write (fd, "CRITICAL **: ", 13);
519       write (fd, message, strlen (message));
520       if (is_fatal)
521         write (fd, "\naborting...\n", 13);
522       else
523         write (fd, "\n", 1);
524       break;
525     case G_LOG_LEVEL_WARNING:
526       if (!log_domain && local_glib_warning_func)
527         {
528           /* compatibility code */
529           local_glib_warning_func (message);
530           return;
531         }
532       ensure_stdout_valid ();
533       write (fd, "\n", 1);
534 #ifdef G_ENABLE_MSG_PREFIX
535       write (fd, prg_name, strlen (prg_name));
536       write (fd, prg_pid, strlen (prg_pid));
537 #endif /* G_ENABLE_MSG_PREFIX */
538       if (log_domain)
539         {
540           write (fd, log_domain, strlen (log_domain));
541           write (fd, "-", 1);
542         }
543       else
544         write (fd, "** ", 3);
545       if (in_recursion)
546         write (fd, "WARNING (recursed) **: ", 23);
547       else
548         write (fd, "WARNING **: ", 12);
549       write (fd, message, strlen (message));
550       if (is_fatal)
551         write (fd, "\naborting...\n", 13);
552       else
553         write (fd, "\n", 1);
554       break;
555     case G_LOG_LEVEL_MESSAGE:
556       if (!log_domain && local_glib_message_func)
557         {
558           /* compatibility code */
559           local_glib_message_func (message);
560           return;
561         }
562       ensure_stdout_valid ();
563 #ifdef G_ENABLE_MSG_PREFIX
564       write (fd, prg_name, strlen (prg_name));
565       write (fd, prg_pid, strlen (prg_pid));
566 #endif /* G_ENABLE_MSG_PREFIX */
567       if (log_domain)
568         {
569           write (fd, log_domain, strlen (log_domain));
570           write (fd, "-", 1);
571         }
572       if (in_recursion)
573         write (fd, "Message (recursed): ", 20);
574       else
575         write (fd, "Message: ", 9);
576       write (fd, message, strlen (message));
577       if (is_fatal)
578         write (fd, "\naborting...\n", 13);
579       else
580         write (fd, "\n", 1);
581       break;
582     case G_LOG_LEVEL_INFO:
583       ensure_stdout_valid ();
584 #ifdef G_ENABLE_MSG_PREFIX
585       write (fd, prg_name, strlen (prg_name));
586       write (fd, prg_pid, strlen (prg_pid));
587 #endif /* G_ENABLE_MSG_PREFIX */
588       if (log_domain)
589         {
590           write (fd, log_domain, strlen (log_domain));
591           write (fd, "-", 1);
592         }
593       if (in_recursion)
594         write (fd, "INFO (recursed): ", 17);
595       else
596         write (fd, "INFO: ", 6);
597       write (fd, message, strlen (message));
598       if (is_fatal)
599         write (fd, "\naborting...\n", 13);
600       else
601         write (fd, "\n", 1);
602       break;
603     case G_LOG_LEVEL_DEBUG:
604       ensure_stdout_valid ();
605 #ifdef G_ENABLE_MSG_PREFIX
606       write (fd, prg_name, strlen (prg_name));
607       write (fd, prg_pid, strlen (prg_pid));
608 #endif /* G_ENABLE_MSG_PREFIX */
609       if (log_domain)
610         {
611           write (fd, log_domain, strlen (log_domain));
612           write (fd, "-", 1);
613         }
614       if (in_recursion)
615         write (fd, "DEBUG (recursed): ", 18);
616       else
617         write (fd, "DEBUG: ", 7);
618       write (fd, message, strlen (message));
619       if (is_fatal)
620         write (fd, "\naborting...\n", 13);
621       else
622         write (fd, "\n", 1);
623       break;
624     default:
625       /* we are used for a log level that is not defined by GLib itself,
626        * try to make the best out of it.
627        */
628       ensure_stdout_valid ();
629 #ifdef G_ENABLE_MSG_PREFIX
630       write (fd, prg_name, strlen (prg_name));
631       write (fd, prg_pid, strlen (prg_pid));
632 #endif /* G_ENABLE_MSG_PREFIX */
633       if (log_domain)
634         {
635           write (fd, log_domain, strlen (log_domain));
636           if (in_recursion)
637             write (fd, "-LOG (recursed:", 15);
638           else
639             write (fd, "-LOG (", 6);
640         }
641       else if (in_recursion)
642         write (fd, "LOG (recursed:", 14);
643       else
644         write (fd, "LOG (", 5);
645       if (log_level)
646         {
647           gchar string[] = "0x00): ";
648           gchar *p = string + 2;
649           guint i;
650           
651           i = g_bit_nth_msf (log_level, -1);
652           *p = i >> 4;
653           p++;
654           *p = '0' + (i & 0xf);
655           if (*p > '9')
656             *p += 'A' - '9' - 1;
657           
658           write (fd, string, 7);
659         }
660       else
661         write (fd, "): ", 3);
662       write (fd, message, strlen (message));
663       if (is_fatal)
664         write (fd, "\naborting...\n", 13);
665       else
666         write (fd, "\n", 1);
667       break;
668     }
669 }
670
671 GPrintFunc
672 g_set_print_handler (GPrintFunc func)
673 {
674   GPrintFunc old_print_func;
675   
676   g_mutex_lock (g_messages_lock);
677   old_print_func = glib_print_func;
678   glib_print_func = func;
679   g_mutex_unlock (g_messages_lock);
680   
681   return old_print_func;
682 }
683
684 void
685 g_print (const gchar *format,
686          ...)
687 {
688   va_list args;
689   gchar *string;
690   GPrintFunc local_glib_print_func;
691   
692   g_return_if_fail (format != NULL);
693   
694   va_start (args, format);
695   string = g_strdup_vprintf (format, args);
696   va_end (args);
697   
698   g_mutex_lock (g_messages_lock);
699   local_glib_print_func = glib_print_func;
700   g_mutex_unlock (g_messages_lock);
701
702   if (local_glib_print_func)
703     local_glib_print_func (string);
704   else
705     {
706       ensure_stdout_valid ();
707       fputs (string, stdout);
708       fflush (stdout);
709     }
710   g_free (string);
711 }
712
713 GPrintFunc
714 g_set_printerr_handler (GPrintFunc func)
715 {
716   GPrintFunc old_printerr_func;
717   
718   g_mutex_lock (g_messages_lock);
719   old_printerr_func = glib_printerr_func;
720   glib_printerr_func = func;
721   g_mutex_unlock (g_messages_lock);
722   
723   return old_printerr_func;
724 }
725
726 void
727 g_printerr (const gchar *format,
728             ...)
729 {
730   va_list args;
731   gchar *string;
732   GPrintFunc local_glib_printerr_func;
733   
734   g_return_if_fail (format != NULL);
735   
736   va_start (args, format);
737   string = g_strdup_vprintf (format, args);
738   va_end (args);
739   
740   g_mutex_lock (g_messages_lock);
741   local_glib_printerr_func = glib_printerr_func;
742   g_mutex_unlock (g_messages_lock);
743
744   if (local_glib_printerr_func)
745     local_glib_printerr_func (string);
746   else
747     {
748       fputs (string, stderr);
749       fflush (stderr);
750     }
751   g_free (string);
752 }
753
754 /* compatibility code */
755 GErrorFunc
756 g_set_error_handler (GErrorFunc func)
757 {
758   GErrorFunc old_error_func;
759   
760   g_mutex_lock (g_messages_lock);
761   old_error_func = glib_error_func;
762   glib_error_func = func;
763   g_mutex_unlock (g_messages_lock);
764  
765   return old_error_func;
766 }
767
768 /* compatibility code */
769 GWarningFunc
770 g_set_warning_handler (GWarningFunc func)
771 {
772   GWarningFunc old_warning_func;
773   
774   g_mutex_lock (g_messages_lock);
775   old_warning_func = glib_warning_func;
776   glib_warning_func = func;
777   g_mutex_unlock (g_messages_lock);
778   
779   return old_warning_func;
780 }
781
782 /* compatibility code */
783 GPrintFunc
784 g_set_message_handler (GPrintFunc func)
785 {
786   GPrintFunc old_message_func;
787   
788   g_mutex_lock (g_messages_lock);
789   old_message_func = glib_message_func;
790   glib_message_func = func;
791   g_mutex_unlock (g_messages_lock);
792   
793   return old_message_func;
794 }
795
796 void
797 g_messages_init (void)
798 {
799   g_messages_lock = g_mutex_new();
800   g_log_depth = g_private_new(NULL);
801 }