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