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