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