]> Pileus Git - ~andy/gtk/blob - glib/gutils.c
Changed LGPL address for FSF in all .h and .c files
[~andy/gtk] / glib / gutils.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 <stdlib.h>
22 #include <string.h>
23 #include <locale.h>
24 #include <ctype.h>              /* For tolower() */
25 #include "glib.h"
26
27
28 static GErrorFunc glib_error_func = NULL;
29 static GWarningFunc glib_warning_func = NULL;
30 static GPrintFunc glib_message_func = NULL;
31 static GPrintFunc glib_print_func = NULL;
32
33 extern char* g_vsprintf (const gchar *fmt, va_list *args, va_list *args2);
34
35 gchar*
36 g_strdup (const gchar *str)
37 {
38   gchar *new_str;
39   
40   new_str = NULL;
41   if (str)
42     {
43       new_str = g_new (char, strlen (str) + 1);
44       strcpy (new_str, str);
45     }
46   
47   return new_str;
48 }
49
50 gchar*
51 g_strconcat (const gchar *string1, ...)
52 {
53   guint   l;
54   va_list args;
55   gchar   *s;
56   gchar   *concat;
57   
58   g_return_val_if_fail (string1 != NULL, NULL);
59   
60   l = 1 + strlen (string1);
61   va_start (args, string1);
62   s = va_arg (args, gchar*);
63   while (s)
64     {
65       l += strlen (s);
66       s = va_arg (args, gchar*);
67     }
68   va_end (args);
69   
70   concat = g_new (gchar, l);
71   concat[0] = 0;
72   
73   strcat (concat, string1);
74   va_start (args, string1);
75   s = va_arg (args, gchar*);
76   while (s)
77     {
78       strcat (concat, s);
79       s = va_arg (args, gchar*);
80     }
81   va_end (args);
82   
83   return concat;
84 }
85
86 gdouble
87 g_strtod (const gchar *nptr,
88           gchar **endptr)
89 {
90   gchar *fail_pos_1;
91   gchar *fail_pos_2;
92   gdouble val_1;
93   gdouble val_2 = 0;
94
95   g_return_val_if_fail (nptr != NULL, 0);
96
97   fail_pos_1 = NULL;
98   fail_pos_2 = NULL;
99
100   val_1 = strtod (nptr, &fail_pos_1);
101
102   if (fail_pos_1 && fail_pos_1[0] != 0)
103     {
104       gchar *old_locale;
105
106       old_locale = setlocale (LC_NUMERIC, "C");
107       val_2 = strtod (nptr, &fail_pos_2);
108       setlocale (LC_NUMERIC, old_locale);
109     }
110
111   if (!fail_pos_1 || fail_pos_1[0] == 0 || fail_pos_1 >= fail_pos_2)
112     {
113       if (endptr)
114         *endptr = fail_pos_1;
115       return val_1;
116     }
117   else
118     {
119       if (endptr)
120         *endptr = fail_pos_2;
121       return val_2;
122     }
123 }
124
125 gchar*
126 g_strerror (gint errnum)
127 {
128   static char msg[64];
129   
130 #ifdef HAVE_STRERROR
131   return strerror (errnum);
132 #elif NO_SYS_ERRLIST
133   switch (errnum)
134     {
135 #ifdef E2BIG
136     case E2BIG: return "argument list too long";
137 #endif
138 #ifdef EACCES
139     case EACCES: return "permission denied";
140 #endif
141 #ifdef EADDRINUSE
142     case EADDRINUSE: return "address already in use";
143 #endif
144 #ifdef EADDRNOTAVAIL
145     case EADDRNOTAVAIL: return "can't assign requested address";
146 #endif
147 #ifdef EADV
148     case EADV: return "advertise error";
149 #endif
150 #ifdef EAFNOSUPPORT
151     case EAFNOSUPPORT: return "address family not supported by protocol family";
152 #endif
153 #ifdef EAGAIN
154     case EAGAIN: return "try again";
155 #endif
156 #ifdef EALIGN
157     case EALIGN: return "EALIGN";
158 #endif
159 #ifdef EALREADY
160     case EALREADY: return "operation already in progress";
161 #endif
162 #ifdef EBADE
163     case EBADE: return "bad exchange descriptor";
164 #endif
165 #ifdef EBADF
166     case EBADF: return "bad file number";
167 #endif
168 #ifdef EBADFD
169     case EBADFD: return "file descriptor in bad state";
170 #endif
171 #ifdef EBADMSG
172     case EBADMSG: return "not a data message";
173 #endif
174 #ifdef EBADR
175     case EBADR: return "bad request descriptor";
176 #endif
177 #ifdef EBADRPC
178     case EBADRPC: return "RPC structure is bad";
179 #endif
180 #ifdef EBADRQC
181     case EBADRQC: return "bad request code";
182 #endif
183 #ifdef EBADSLT
184     case EBADSLT: return "invalid slot";
185 #endif
186 #ifdef EBFONT
187     case EBFONT: return "bad font file format";
188 #endif
189 #ifdef EBUSY
190     case EBUSY: return "mount device busy";
191 #endif
192 #ifdef ECHILD
193     case ECHILD: return "no children";
194 #endif
195 #ifdef ECHRNG
196     case ECHRNG: return "channel number out of range";
197 #endif
198 #ifdef ECOMM
199     case ECOMM: return "communication error on send";
200 #endif
201 #ifdef ECONNABORTED
202     case ECONNABORTED: return "software caused connection abort";
203 #endif
204 #ifdef ECONNREFUSED
205     case ECONNREFUSED: return "connection refused";
206 #endif
207 #ifdef ECONNRESET
208     case ECONNRESET: return "connection reset by peer";
209 #endif
210 #if defined(EDEADLK) && (!defined(EWOULDBLOCK) || (EDEADLK != EWOULDBLOCK))
211     case EDEADLK: return "resource deadlock avoided";
212 #endif
213 #ifdef EDEADLOCK
214     case EDEADLOCK: return "resource deadlock avoided";
215 #endif
216 #ifdef EDESTADDRREQ
217     case EDESTADDRREQ: return "destination address required";
218 #endif
219 #ifdef EDIRTY
220     case EDIRTY: return "mounting a dirty fs w/o force";
221 #endif
222 #ifdef EDOM
223     case EDOM: return "math argument out of range";
224 #endif
225 #ifdef EDOTDOT
226     case EDOTDOT: return "cross mount point";
227 #endif
228 #ifdef EDQUOT
229     case EDQUOT: return "disk quota exceeded";
230 #endif
231 #ifdef EDUPPKG
232     case EDUPPKG: return "duplicate package name";
233 #endif
234 #ifdef EEXIST
235     case EEXIST: return "file already exists";
236 #endif
237 #ifdef EFAULT
238     case EFAULT: return "bad address in system call argument";
239 #endif
240 #ifdef EFBIG
241     case EFBIG: return "file too large";
242 #endif
243 #ifdef EHOSTDOWN
244     case EHOSTDOWN: return "host is down";
245 #endif
246 #ifdef EHOSTUNREACH
247     case EHOSTUNREACH: return "host is unreachable";
248 #endif
249 #ifdef EIDRM
250     case EIDRM: return "identifier removed";
251 #endif
252 #ifdef EINIT
253     case EINIT: return "initialization error";
254 #endif
255 #ifdef EINPROGRESS
256     case EINPROGRESS: return "operation now in progress";
257 #endif
258 #ifdef EINTR
259     case EINTR: return "interrupted system call";
260 #endif
261 #ifdef EINVAL
262     case EINVAL: return "invalid argument";
263 #endif
264 #ifdef EIO
265     case EIO: return "I/O error";
266 #endif
267 #ifdef EISCONN
268     case EISCONN: return "socket is already connected";
269 #endif
270 #ifdef EISDIR
271     case EISDIR: return "illegal operation on a directory";
272 #endif
273 #ifdef EISNAME
274     case EISNAM: return "is a name file";
275 #endif
276 #ifdef ELBIN
277     case ELBIN: return "ELBIN";
278 #endif
279 #ifdef EL2HLT
280     case EL2HLT: return "level 2 halted";
281 #endif
282 #ifdef EL2NSYNC
283     case EL2NSYNC: return "level 2 not synchronized";
284 #endif
285 #ifdef EL3HLT
286     case EL3HLT: return "level 3 halted";
287 #endif
288 #ifdef EL3RST
289     case EL3RST: return "level 3 reset";
290 #endif
291 #ifdef ELIBACC
292     case ELIBACC: return "can not access a needed shared library";
293 #endif
294 #ifdef ELIBBAD
295     case ELIBBAD: return "accessing a corrupted shared library";
296 #endif
297 #ifdef ELIBEXEC
298     case ELIBEXEC: return "can not exec a shared library directly";
299 #endif
300 #ifdef ELIBMAX
301     case ELIBMAX: return "attempting to link in more shared libraries than system limit";
302 #endif
303 #ifdef ELIBSCN
304     case ELIBSCN: return ".lib section in a.out corrupted";
305 #endif
306 #ifdef ELNRNG
307     case ELNRNG: return "link number out of range";
308 #endif
309 #ifdef ELOOP
310     case ELOOP: return "too many levels of symbolic links";
311 #endif
312 #ifdef EMFILE
313     case EMFILE: return "too many open files";
314 #endif
315 #ifdef EMLINK
316     case EMLINK: return "too many links";
317 #endif
318 #ifdef EMSGSIZE
319     case EMSGSIZE: return "message too long";
320 #endif
321 #ifdef EMULTIHOP
322     case EMULTIHOP: return "multihop attempted";
323 #endif
324 #ifdef ENAMETOOLONG
325     case ENAMETOOLONG: return "file name too long";
326 #endif
327 #ifdef ENAVAIL
328     case ENAVAIL: return "not available";
329 #endif
330 #ifdef ENET
331     case ENET: return "ENET";
332 #endif
333 #ifdef ENETDOWN
334     case ENETDOWN: return "network is down";
335 #endif
336 #ifdef ENETRESET
337     case ENETRESET: return "network dropped connection on reset";
338 #endif
339 #ifdef ENETUNREACH
340     case ENETUNREACH: return "network is unreachable";
341 #endif
342 #ifdef ENFILE
343     case ENFILE: return "file table overflow";
344 #endif
345 #ifdef ENOANO
346     case ENOANO: return "anode table overflow";
347 #endif
348 #if defined(ENOBUFS) && (!defined(ENOSR) || (ENOBUFS != ENOSR))
349     case ENOBUFS: return "no buffer space available";
350 #endif
351 #ifdef ENOCSI
352     case ENOCSI: return "no CSI structure available";
353 #endif
354 #ifdef ENODATA
355     case ENODATA: return "no data available";
356 #endif
357 #ifdef ENODEV
358     case ENODEV: return "no such device";
359 #endif
360 #ifdef ENOENT
361     case ENOENT: return "no such file or directory";
362 #endif
363 #ifdef ENOEXEC
364     case ENOEXEC: return "exec format error";
365 #endif
366 #ifdef ENOLCK
367     case ENOLCK: return "no locks available";
368 #endif
369 #ifdef ENOLINK
370     case ENOLINK: return "link has be severed";
371 #endif
372 #ifdef ENOMEM
373     case ENOMEM: return "not enough memory";
374 #endif
375 #ifdef ENOMSG
376     case ENOMSG: return "no message of desired type";
377 #endif
378 #ifdef ENONET
379     case ENONET: return "machine is not on the network";
380 #endif
381 #ifdef ENOPKG
382     case ENOPKG: return "package not installed";
383 #endif
384 #ifdef ENOPROTOOPT
385     case ENOPROTOOPT: return "bad proocol option";
386 #endif
387 #ifdef ENOSPC
388     case ENOSPC: return "no space left on device";
389 #endif
390 #ifdef ENOSR
391     case ENOSR: return "out of stream resources";
392 #endif
393 #ifdef ENOSTR
394     case ENOSTR: return "not a stream device";
395 #endif
396 #ifdef ENOSYM
397     case ENOSYM: return "unresolved symbol name";
398 #endif
399 #ifdef ENOSYS
400     case ENOSYS: return "function not implemented";
401 #endif
402 #ifdef ENOTBLK
403     case ENOTBLK: return "block device required";
404 #endif
405 #ifdef ENOTCONN
406     case ENOTCONN: return "socket is not connected";
407 #endif
408 #ifdef ENOTDIR
409     case ENOTDIR: return "not a directory";
410 #endif
411 #ifdef ENOTEMPTY
412     case ENOTEMPTY: return "directory not empty";
413 #endif
414 #ifdef ENOTNAM
415     case ENOTNAM: return "not a name file";
416 #endif
417 #ifdef ENOTSOCK
418     case ENOTSOCK: return "socket operation on non-socket";
419 #endif
420 #ifdef ENOTTY
421     case ENOTTY: return "inappropriate device for ioctl";
422 #endif
423 #ifdef ENOTUNIQ
424     case ENOTUNIQ: return "name not unique on network";
425 #endif
426 #ifdef ENXIO
427     case ENXIO: return "no such device or address";
428 #endif
429 #ifdef EOPNOTSUPP
430     case EOPNOTSUPP: return "operation not supported on socket";
431 #endif
432 #ifdef EPERM
433     case EPERM: return "not owner";
434 #endif
435 #ifdef EPFNOSUPPORT
436     case EPFNOSUPPORT: return "protocol family not supported";
437 #endif
438 #ifdef EPIPE
439     case EPIPE: return "broken pipe";
440 #endif
441 #ifdef EPROCLIM
442     case EPROCLIM: return "too many processes";
443 #endif
444 #ifdef EPROCUNAVAIL
445     case EPROCUNAVAIL: return "bad procedure for program";
446 #endif
447 #ifdef EPROGMISMATCH
448     case EPROGMISMATCH: return "program version wrong";
449 #endif
450 #ifdef EPROGUNAVAIL
451     case EPROGUNAVAIL: return "RPC program not available";
452 #endif
453 #ifdef EPROTO
454     case EPROTO: return "protocol error";
455 #endif
456 #ifdef EPROTONOSUPPORT
457     case EPROTONOSUPPORT: return "protocol not suppored";
458 #endif
459 #ifdef EPROTOTYPE
460     case EPROTOTYPE: return "protocol wrong type for socket";
461 #endif
462 #ifdef ERANGE
463     case ERANGE: return "math result unrepresentable";
464 #endif
465 #if defined(EREFUSED) && (!defined(ECONNREFUSED) || (EREFUSED != ECONNREFUSED))
466     case EREFUSED: return "EREFUSED";
467 #endif
468 #ifdef EREMCHG
469     case EREMCHG: return "remote address changed";
470 #endif
471 #ifdef EREMDEV
472     case EREMDEV: return "remote device";
473 #endif
474 #ifdef EREMOTE
475     case EREMOTE: return "pathname hit remote file system";
476 #endif
477 #ifdef EREMOTEIO
478     case EREMOTEIO: return "remote i/o error";
479 #endif
480 #ifdef EREMOTERELEASE
481     case EREMOTERELEASE: return "EREMOTERELEASE";
482 #endif
483 #ifdef EROFS
484     case EROFS: return "read-only file system";
485 #endif
486 #ifdef ERPCMISMATCH
487     case ERPCMISMATCH: return "RPC version is wrong";
488 #endif
489 #ifdef ERREMOTE
490     case ERREMOTE: return "object is remote";
491 #endif
492 #ifdef ESHUTDOWN
493     case ESHUTDOWN: return "can't send afer socket shutdown";
494 #endif
495 #ifdef ESOCKTNOSUPPORT
496     case ESOCKTNOSUPPORT: return "socket type not supported";
497 #endif
498 #ifdef ESPIPE
499     case ESPIPE: return "invalid seek";
500 #endif
501 #ifdef ESRCH
502     case ESRCH: return "no such process";
503 #endif
504 #ifdef ESRMNT
505     case ESRMNT: return "srmount error";
506 #endif
507 #ifdef ESTALE
508     case ESTALE: return "stale remote file handle";
509 #endif
510 #ifdef ESUCCESS
511     case ESUCCESS: return "Error 0";
512 #endif
513 #ifdef ETIME
514     case ETIME: return "timer expired";
515 #endif
516 #ifdef ETIMEDOUT
517     case ETIMEDOUT: return "connection timed out";
518 #endif
519 #ifdef ETOOMANYREFS
520     case ETOOMANYREFS: return "too many references: can't splice";
521 #endif
522 #ifdef ETXTBSY
523     case ETXTBSY: return "text file or pseudo-device busy";
524 #endif
525 #ifdef EUCLEAN
526     case EUCLEAN: return "structure needs cleaning";
527 #endif
528 #ifdef EUNATCH
529     case EUNATCH: return "protocol driver not attached";
530 #endif
531 #ifdef EUSERS
532     case EUSERS: return "too many users";
533 #endif
534 #ifdef EVERSION
535     case EVERSION: return "version mismatch";
536 #endif
537 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
538     case EWOULDBLOCK: return "operation would block";
539 #endif
540 #ifdef EXDEV
541     case EXDEV: return "cross-domain link";
542 #endif
543 #ifdef EXFULL
544     case EXFULL: return "message tables full";
545 #endif
546     }
547 #else /* NO_SYS_ERRLIST */
548   extern int sys_nerr;
549   extern char *sys_errlist[];
550
551   if ((errnum > 0) && (errnum <= sys_nerr))
552     return sys_errlist [errnum];
553 #endif /* NO_SYS_ERRLIST */
554
555   sprintf (msg, "unknown error (%d)", errnum);
556   return msg;
557 }
558
559 gchar*
560 g_strsignal (gint signum)
561 {
562   static char msg[64];
563
564 #ifdef HAVE_STRSIGNAL
565   extern char *strsignal (int sig);
566   return strsignal (signum);
567 #elif NO_SYS_SIGLIST
568   switch (signum)
569     {
570 #ifdef SIGHUP
571     case SIGHUP: return "Hangup";
572 #endif
573 #ifdef SIGINT
574     case SIGINT: return "Interrupt";
575 #endif
576 #ifdef SIGQUIT
577     case SIGQUIT: return "Quit";
578 #endif
579 #ifdef SIGILL
580     case SIGILL: "Illegal instruction";
581 #endif
582 #ifdef SIGTRAP
583     case SIGTRAP: "Trace/breakpoint trap";
584 #endif
585 #ifdef SIGABRT
586     case SIGABRT: "IOT trap/Abort";
587 #endif
588 #ifdef SIGBUS
589     case SIGBUS: "Bus error";
590 #endif
591 #ifdef SIGFPE
592     case SIGFPE: "Floating point exception";
593 #endif
594 #ifdef SIGKILL
595     case SIGKILL: "Killed";
596 #endif
597 #ifdef SIGUSR1
598     case SIGUSR1: "User defined signal 1";
599 #endif
600 #ifdef SIGSEGV
601     case SIGSEGV: "Segmentation fault";
602 #endif
603 #ifdef SIGUSR2
604     case SIGUSR2: "User defined signal 2";
605 #endif
606 #ifdef SIGPIPE
607     case SIGPIPE: "Broken pipe";
608 #endif
609 #ifdef SIGALRM
610     case SIGALRM: "Alarm clock";
611 #endif
612 #ifdef SIGTERM
613     case SIGTERM: "Terminated";
614 #endif
615 #ifdef SIGSTKFLT
616     case SIGSTKFLT: "Stack fault";
617 #endif
618 #ifdef SIGCHLD
619     case SIGCHLD: "Child exited";
620 #endif
621 #ifdef SIGCONT
622     case SIGCONT: "Continued";
623 #endif
624 #ifdef SIGSTOP
625     case SIGSTOP: "Stopped (signal)";
626 #endif
627 #ifdef SIGTSTP
628     case SIGTSTP: "Stopped";
629 #endif
630 #ifdef SIGTTIN
631     case SIGTTIN: "Stopped (tty input)";
632 #endif
633 #ifdef SIGTTOU
634     case SIGTTOU: "Stopped (tty output)";
635 #endif
636 #ifdef SIGURG
637     case SIGURG: "Urgent condition";
638 #endif
639 #ifdef SIGXCPU
640     case SIGXCPU: "CPU time limit exceeded";
641 #endif
642 #ifdef SIGXFSZ
643     case SIGXFSZ: "File size limit exceeded";
644 #endif
645 #ifdef SIGVTALRM
646     case SIGVTALRM: "Virtual time alarm";
647 #endif
648 #ifdef SIGPROF
649     case SIGPROF: "Profile signal";
650 #endif
651 #ifdef SIGWINCH
652     case SIGWINCH: "Window size changed";
653 #endif
654 #ifdef SIGIO
655     case SIGIO: "Possible I/O";
656 #endif
657 #ifdef SIGPWR
658     case SIGPWR: "Power failure";
659 #endif
660 #ifdef SIGUNUSED
661     case SIGUNUSED: return "Unused signal";
662 #endif
663     }
664 #else /* NO_SYS_SIGLIST */
665   extern char *sys_siglist[];
666   return sys_siglist [signum];
667 #endif /* NO_SYS_SIGLIST */
668
669   sprintf (msg, "unknown signal (%d)", signum);
670   return msg;
671 }
672
673 void
674 g_error (gchar *format, ...)
675 {
676   va_list args, args2;
677   char *buf;
678
679   va_start (args, format);
680   va_start (args2, format);
681   buf = g_vsprintf (format, &args, &args2);
682   va_end (args);
683   va_end (args2);
684
685   if (glib_error_func)
686     {
687       (* glib_error_func) (buf);
688     }
689   else
690     {
691       fputs ("\n** ERROR **: ", stderr);
692       fputs (buf, stderr);
693       fputc ('\n', stderr);
694     }
695
696   abort ();
697 }
698
699 void
700 g_warning (gchar *format, ...)
701 {
702   va_list args, args2;
703   char *buf;
704
705   va_start (args, format);
706   va_start (args2, format);
707   buf = g_vsprintf (format, &args, &args2);
708   va_end (args);
709   va_end (args2);
710
711   if (glib_warning_func)
712     {
713       (* glib_warning_func) (buf);
714     }
715   else
716     {
717       fputs ("\n** WARNING **: ", stderr);
718       fputs (buf, stderr);
719       fputc ('\n', stderr);
720     }
721 }
722
723 void
724 g_message (gchar *format, ...)
725 {
726   va_list args, args2;
727   char *buf;
728
729   va_start (args, format);
730   va_start (args2, format);
731   buf = g_vsprintf (format, &args, &args2);
732   va_end (args);
733   va_end (args2);
734
735   if (glib_message_func)
736     {
737       (* glib_message_func) (buf);
738     }
739   else
740     {
741       fputs ("message: ", stdout);
742       fputs (buf, stdout);
743       fputc ('\n', stdout);
744     }
745 }
746
747 void
748 g_print (gchar *format, ...)
749 {
750   va_list args, args2;
751   char *buf;
752
753   va_start (args, format);
754   va_start (args2, format);
755   buf = g_vsprintf (format, &args, &args2);
756   va_end (args);
757   va_end (args2);
758
759   if (glib_print_func)
760     {
761       (* glib_print_func) (buf);
762     }
763   else
764     {
765       fputs (buf, stdout);
766     }
767 }
768
769 GErrorFunc
770 g_set_error_handler (GErrorFunc func)
771 {
772   GErrorFunc old_error_func;
773
774   old_error_func = glib_error_func;
775   glib_error_func = func;
776
777   return old_error_func;
778 }
779
780 GWarningFunc
781 g_set_warning_handler (GWarningFunc func)
782 {
783   GWarningFunc old_warning_func;
784
785   old_warning_func = glib_warning_func;
786   glib_warning_func = func;
787
788   return old_warning_func;
789 }
790
791 GPrintFunc
792 g_set_message_handler (GPrintFunc func)
793 {
794   GPrintFunc old_message_func;
795
796   old_message_func = glib_message_func;
797   glib_message_func = func;
798
799   return old_message_func;
800 }
801
802 GPrintFunc
803 g_set_print_handler (GPrintFunc func)
804 {
805   GPrintFunc old_print_func;
806
807   old_print_func = glib_print_func;
808   glib_print_func = func;
809   
810   return old_print_func;
811 }
812
813 gint
814 g_snprintf (gchar       *str,
815             gulong       n,
816             gchar const *fmt,
817             ...)
818 {
819 #ifdef HAVE_VSNPRINTF
820   va_list args;
821   gint retval;
822   
823   va_start (args, fmt);
824   retval = vsnprintf (str, n, fmt, args);
825   va_end (args);
826
827   return retval;
828
829 #else
830   gchar *printed;
831   va_list args, args2;
832
833   va_start (args, fmt);
834   va_start (args2, fmt);
835   
836   printed = g_vsprintf (fmt, &args, &args2);
837   strncpy (str, printed, n);
838   str[n-1] = '\0';
839   
840   va_end (args2);
841   va_end (args);
842
843   return strlen (str);
844
845 #endif
846 }
847
848 gint
849 g_strcasecmp (const gchar *s1, const gchar *s2)
850 {
851 #ifdef HAVE_STRCASECMP
852   return strcasecmp(s1, s2);
853 #else
854   gint c1, c2;
855
856   while (*s1 && *s2)
857     {
858       c1 = tolower((guchar)(*s1++)); c2 = tolower((guchar)(*s2++));
859       if (c1 != c2)
860         return (c1 - c2);
861     }
862
863   return (((gint)(guchar) *s1) - ((gint)(guchar) *s2));
864 #endif
865 }
866
867 guint        
868 g_parse_debug_string  (const gchar *string, 
869                        GDebugKey   *keys, 
870                        guint        nkeys)
871 {
872   guint i;
873   guint result = 0;
874
875   g_return_val_if_fail (string != NULL, 0);
876
877   if (!g_strcasecmp (string, "all"))
878     {
879       for (i=0; i<nkeys; i++)
880         result |= keys[i].value;
881     }
882   else
883     {
884       gchar *str = g_strdup (string);
885       gchar *p = str;
886       gchar *q;
887       gboolean done = FALSE;
888
889       while (*p && !done)
890         {
891           q = strchr (p, ':');
892           if (!q)
893             {
894               q = p + strlen(p);
895               done = TRUE;
896             }
897
898           *q = 0;
899
900           for (i=0; i<nkeys; i++)
901             if (!g_strcasecmp(keys[i].key, p))
902               result |= keys[i].value;
903
904           p = q+1;
905         }
906       
907       g_free (str);
908     }
909
910   return result;
911 }
912
913 guint
914 g_direct_hash(gpointer key)
915 {
916   return (guint) key;
917 }
918