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