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