cleaned up the errno mess for GETPWUID. we especially don't want to
[platform/upstream/glib.git] / gstrfuncs.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
20 /*
21  * MT safe
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdarg.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <locale.h>
33 #include <ctype.h>              /* For tolower() */
34 #if !defined (HAVE_STRSIGNAL) && NO_SYS_SIGLIST
35 #include <signal.h>
36 #endif
37 #include "glib.h"
38 /* do not include <unistd.h> in this place since it
39  * inteferes with g_strsignal() on some OSes
40  */
41
42 gchar*
43 g_strdup (const gchar *str)
44 {
45   gchar *new_str;
46
47   if (str)
48     {
49       new_str = g_new (char, strlen (str) + 1);
50       strcpy (new_str, str);
51     }
52   else
53     new_str = NULL;
54
55   return new_str;
56 }
57
58 gpointer
59 g_memdup (gconstpointer mem,
60           guint         byte_size)
61 {
62   gpointer new_mem;
63
64   if (mem)
65     {
66       new_mem = g_malloc (byte_size);
67       memcpy (new_mem, mem, byte_size);
68     }
69   else
70     new_mem = NULL;
71
72   return new_mem;
73 }
74
75 gchar*
76 g_strndup (const gchar *str,
77            guint        n)
78 {
79   gchar *new_str;
80
81   if (str)
82     {
83       new_str = g_new (gchar, n + 1);
84       strncpy (new_str, str, n);
85       new_str[n] = '\0';
86     }
87   else
88     new_str = NULL;
89
90   return new_str;
91 }
92
93 gchar*
94 g_strnfill (guint length,
95             gchar fill_char)
96 {
97   register gchar *str, *s, *end;
98
99   str = g_new (gchar, length + 1);
100   s = str;
101   end = str + length;
102   while (s < end)
103     *(s++) = fill_char;
104   *s = 0;
105
106   return str;
107 }
108
109 gchar*
110 g_strdup_vprintf (const gchar *format,
111                   va_list      args1)
112 {
113   gchar *buffer;
114   va_list args2;
115
116   G_VA_COPY (args2, args1);
117
118   buffer = g_new (gchar, g_printf_string_upper_bound (format, args1));
119
120   vsprintf (buffer, format, args2);
121   va_end (args2);
122
123   return buffer;
124 }
125
126 gchar*
127 g_strdup_printf (const gchar *format,
128                  ...)
129 {
130   gchar *buffer;
131   va_list args;
132
133   va_start (args, format);
134   buffer = g_strdup_vprintf (format, args);
135   va_end (args);
136
137   return buffer;
138 }
139
140 gchar*
141 g_strconcat (const gchar *string1, ...)
142 {
143   guint   l;
144   va_list args;
145   gchar   *s;
146   gchar   *concat;
147
148   g_return_val_if_fail (string1 != NULL, NULL);
149
150   l = 1 + strlen (string1);
151   va_start (args, string1);
152   s = va_arg (args, gchar*);
153   while (s)
154     {
155       l += strlen (s);
156       s = va_arg (args, gchar*);
157     }
158   va_end (args);
159
160   concat = g_new (gchar, l);
161   concat[0] = 0;
162
163   strcat (concat, string1);
164   va_start (args, string1);
165   s = va_arg (args, gchar*);
166   while (s)
167     {
168       strcat (concat, s);
169       s = va_arg (args, gchar*);
170     }
171   va_end (args);
172
173   return concat;
174 }
175
176 gdouble
177 g_strtod (const gchar *nptr,
178           gchar **endptr)
179 {
180   gchar *fail_pos_1;
181   gchar *fail_pos_2;
182   gdouble val_1;
183   gdouble val_2 = 0;
184
185   g_return_val_if_fail (nptr != NULL, 0);
186
187   fail_pos_1 = NULL;
188   fail_pos_2 = NULL;
189
190   val_1 = strtod (nptr, &fail_pos_1);
191
192   if (fail_pos_1 && fail_pos_1[0] != 0)
193     {
194       gchar *old_locale;
195
196       old_locale = setlocale (LC_NUMERIC, "C");
197       val_2 = strtod (nptr, &fail_pos_2);
198       setlocale (LC_NUMERIC, old_locale);
199     }
200
201   if (!fail_pos_1 || fail_pos_1[0] == 0 || fail_pos_1 >= fail_pos_2)
202     {
203       if (endptr)
204         *endptr = fail_pos_1;
205       return val_1;
206     }
207   else
208     {
209       if (endptr)
210         *endptr = fail_pos_2;
211       return val_2;
212     }
213 }
214
215 gchar*
216 g_strerror (gint errnum)
217 {
218   static GStaticPrivate msg_private = G_STATIC_PRIVATE_INIT;
219   char *msg;
220
221 #ifdef HAVE_STRERROR
222   return strerror (errnum);
223 #elif NO_SYS_ERRLIST
224   switch (errnum)
225     {
226 #ifdef E2BIG
227     case E2BIG: return "argument list too long";
228 #endif
229 #ifdef EACCES
230     case EACCES: return "permission denied";
231 #endif
232 #ifdef EADDRINUSE
233     case EADDRINUSE: return "address already in use";
234 #endif
235 #ifdef EADDRNOTAVAIL
236     case EADDRNOTAVAIL: return "can't assign requested address";
237 #endif
238 #ifdef EADV
239     case EADV: return "advertise error";
240 #endif
241 #ifdef EAFNOSUPPORT
242     case EAFNOSUPPORT: return "address family not supported by protocol family";
243 #endif
244 #ifdef EAGAIN
245     case EAGAIN: return "try again";
246 #endif
247 #ifdef EALIGN
248     case EALIGN: return "EALIGN";
249 #endif
250 #ifdef EALREADY
251     case EALREADY: return "operation already in progress";
252 #endif
253 #ifdef EBADE
254     case EBADE: return "bad exchange descriptor";
255 #endif
256 #ifdef EBADF
257     case EBADF: return "bad file number";
258 #endif
259 #ifdef EBADFD
260     case EBADFD: return "file descriptor in bad state";
261 #endif
262 #ifdef EBADMSG
263     case EBADMSG: return "not a data message";
264 #endif
265 #ifdef EBADR
266     case EBADR: return "bad request descriptor";
267 #endif
268 #ifdef EBADRPC
269     case EBADRPC: return "RPC structure is bad";
270 #endif
271 #ifdef EBADRQC
272     case EBADRQC: return "bad request code";
273 #endif
274 #ifdef EBADSLT
275     case EBADSLT: return "invalid slot";
276 #endif
277 #ifdef EBFONT
278     case EBFONT: return "bad font file format";
279 #endif
280 #ifdef EBUSY
281     case EBUSY: return "mount device busy";
282 #endif
283 #ifdef ECHILD
284     case ECHILD: return "no children";
285 #endif
286 #ifdef ECHRNG
287     case ECHRNG: return "channel number out of range";
288 #endif
289 #ifdef ECOMM
290     case ECOMM: return "communication error on send";
291 #endif
292 #ifdef ECONNABORTED
293     case ECONNABORTED: return "software caused connection abort";
294 #endif
295 #ifdef ECONNREFUSED
296     case ECONNREFUSED: return "connection refused";
297 #endif
298 #ifdef ECONNRESET
299     case ECONNRESET: return "connection reset by peer";
300 #endif
301 #if defined(EDEADLK) && (!defined(EWOULDBLOCK) || (EDEADLK != EWOULDBLOCK))
302     case EDEADLK: return "resource deadlock avoided";
303 #endif
304 #ifdef EDEADLOCK
305     case EDEADLOCK: return "resource deadlock avoided";
306 #endif
307 #ifdef EDESTADDRREQ
308     case EDESTADDRREQ: return "destination address required";
309 #endif
310 #ifdef EDIRTY
311     case EDIRTY: return "mounting a dirty fs w/o force";
312 #endif
313 #ifdef EDOM
314     case EDOM: return "math argument out of range";
315 #endif
316 #ifdef EDOTDOT
317     case EDOTDOT: return "cross mount point";
318 #endif
319 #ifdef EDQUOT
320     case EDQUOT: return "disk quota exceeded";
321 #endif
322 #ifdef EDUPPKG
323     case EDUPPKG: return "duplicate package name";
324 #endif
325 #ifdef EEXIST
326     case EEXIST: return "file already exists";
327 #endif
328 #ifdef EFAULT
329     case EFAULT: return "bad address in system call argument";
330 #endif
331 #ifdef EFBIG
332     case EFBIG: return "file too large";
333 #endif
334 #ifdef EHOSTDOWN
335     case EHOSTDOWN: return "host is down";
336 #endif
337 #ifdef EHOSTUNREACH
338     case EHOSTUNREACH: return "host is unreachable";
339 #endif
340 #ifdef EIDRM
341     case EIDRM: return "identifier removed";
342 #endif
343 #ifdef EINIT
344     case EINIT: return "initialization error";
345 #endif
346 #ifdef EINPROGRESS
347     case EINPROGRESS: return "operation now in progress";
348 #endif
349 #ifdef EINTR
350     case EINTR: return "interrupted system call";
351 #endif
352 #ifdef EINVAL
353     case EINVAL: return "invalid argument";
354 #endif
355 #ifdef EIO
356     case EIO: return "I/O error";
357 #endif
358 #ifdef EISCONN
359     case EISCONN: return "socket is already connected";
360 #endif
361 #ifdef EISDIR
362     case EISDIR: return "illegal operation on a directory";
363 #endif
364 #ifdef EISNAME
365     case EISNAM: return "is a name file";
366 #endif
367 #ifdef ELBIN
368     case ELBIN: return "ELBIN";
369 #endif
370 #ifdef EL2HLT
371     case EL2HLT: return "level 2 halted";
372 #endif
373 #ifdef EL2NSYNC
374     case EL2NSYNC: return "level 2 not synchronized";
375 #endif
376 #ifdef EL3HLT
377     case EL3HLT: return "level 3 halted";
378 #endif
379 #ifdef EL3RST
380     case EL3RST: return "level 3 reset";
381 #endif
382 #ifdef ELIBACC
383     case ELIBACC: return "can not access a needed shared library";
384 #endif
385 #ifdef ELIBBAD
386     case ELIBBAD: return "accessing a corrupted shared library";
387 #endif
388 #ifdef ELIBEXEC
389     case ELIBEXEC: return "can not exec a shared library directly";
390 #endif
391 #ifdef ELIBMAX
392     case ELIBMAX: return "attempting to link in more shared libraries than system limit";
393 #endif
394 #ifdef ELIBSCN
395     case ELIBSCN: return ".lib section in a.out corrupted";
396 #endif
397 #ifdef ELNRNG
398     case ELNRNG: return "link number out of range";
399 #endif
400 #ifdef ELOOP
401     case ELOOP: return "too many levels of symbolic links";
402 #endif
403 #ifdef EMFILE
404     case EMFILE: return "too many open files";
405 #endif
406 #ifdef EMLINK
407     case EMLINK: return "too many links";
408 #endif
409 #ifdef EMSGSIZE
410     case EMSGSIZE: return "message too long";
411 #endif
412 #ifdef EMULTIHOP
413     case EMULTIHOP: return "multihop attempted";
414 #endif
415 #ifdef ENAMETOOLONG
416     case ENAMETOOLONG: return "file name too long";
417 #endif
418 #ifdef ENAVAIL
419     case ENAVAIL: return "not available";
420 #endif
421 #ifdef ENET
422     case ENET: return "ENET";
423 #endif
424 #ifdef ENETDOWN
425     case ENETDOWN: return "network is down";
426 #endif
427 #ifdef ENETRESET
428     case ENETRESET: return "network dropped connection on reset";
429 #endif
430 #ifdef ENETUNREACH
431     case ENETUNREACH: return "network is unreachable";
432 #endif
433 #ifdef ENFILE
434     case ENFILE: return "file table overflow";
435 #endif
436 #ifdef ENOANO
437     case ENOANO: return "anode table overflow";
438 #endif
439 #if defined(ENOBUFS) && (!defined(ENOSR) || (ENOBUFS != ENOSR))
440     case ENOBUFS: return "no buffer space available";
441 #endif
442 #ifdef ENOCSI
443     case ENOCSI: return "no CSI structure available";
444 #endif
445 #ifdef ENODATA
446     case ENODATA: return "no data available";
447 #endif
448 #ifdef ENODEV
449     case ENODEV: return "no such device";
450 #endif
451 #ifdef ENOENT
452     case ENOENT: return "no such file or directory";
453 #endif
454 #ifdef ENOEXEC
455     case ENOEXEC: return "exec format error";
456 #endif
457 #ifdef ENOLCK
458     case ENOLCK: return "no locks available";
459 #endif
460 #ifdef ENOLINK
461     case ENOLINK: return "link has be severed";
462 #endif
463 #ifdef ENOMEM
464     case ENOMEM: return "not enough memory";
465 #endif
466 #ifdef ENOMSG
467     case ENOMSG: return "no message of desired type";
468 #endif
469 #ifdef ENONET
470     case ENONET: return "machine is not on the network";
471 #endif
472 #ifdef ENOPKG
473     case ENOPKG: return "package not installed";
474 #endif
475 #ifdef ENOPROTOOPT
476     case ENOPROTOOPT: return "bad proocol option";
477 #endif
478 #ifdef ENOSPC
479     case ENOSPC: return "no space left on device";
480 #endif
481 #ifdef ENOSR
482     case ENOSR: return "out of stream resources";
483 #endif
484 #ifdef ENOSTR
485     case ENOSTR: return "not a stream device";
486 #endif
487 #ifdef ENOSYM
488     case ENOSYM: return "unresolved symbol name";
489 #endif
490 #ifdef ENOSYS
491     case ENOSYS: return "function not implemented";
492 #endif
493 #ifdef ENOTBLK
494     case ENOTBLK: return "block device required";
495 #endif
496 #ifdef ENOTCONN
497     case ENOTCONN: return "socket is not connected";
498 #endif
499 #ifdef ENOTDIR
500     case ENOTDIR: return "not a directory";
501 #endif
502 #ifdef ENOTEMPTY
503     case ENOTEMPTY: return "directory not empty";
504 #endif
505 #ifdef ENOTNAM
506     case ENOTNAM: return "not a name file";
507 #endif
508 #ifdef ENOTSOCK
509     case ENOTSOCK: return "socket operation on non-socket";
510 #endif
511 #ifdef ENOTTY
512     case ENOTTY: return "inappropriate device for ioctl";
513 #endif
514 #ifdef ENOTUNIQ
515     case ENOTUNIQ: return "name not unique on network";
516 #endif
517 #ifdef ENXIO
518     case ENXIO: return "no such device or address";
519 #endif
520 #ifdef EOPNOTSUPP
521     case EOPNOTSUPP: return "operation not supported on socket";
522 #endif
523 #ifdef EPERM
524     case EPERM: return "not owner";
525 #endif
526 #ifdef EPFNOSUPPORT
527     case EPFNOSUPPORT: return "protocol family not supported";
528 #endif
529 #ifdef EPIPE
530     case EPIPE: return "broken pipe";
531 #endif
532 #ifdef EPROCLIM
533     case EPROCLIM: return "too many processes";
534 #endif
535 #ifdef EPROCUNAVAIL
536     case EPROCUNAVAIL: return "bad procedure for program";
537 #endif
538 #ifdef EPROGMISMATCH
539     case EPROGMISMATCH: return "program version wrong";
540 #endif
541 #ifdef EPROGUNAVAIL
542     case EPROGUNAVAIL: return "RPC program not available";
543 #endif
544 #ifdef EPROTO
545     case EPROTO: return "protocol error";
546 #endif
547 #ifdef EPROTONOSUPPORT
548     case EPROTONOSUPPORT: return "protocol not suppored";
549 #endif
550 #ifdef EPROTOTYPE
551     case EPROTOTYPE: return "protocol wrong type for socket";
552 #endif
553 #ifdef ERANGE
554     case ERANGE: return "math result unrepresentable";
555 #endif
556 #if defined(EREFUSED) && (!defined(ECONNREFUSED) || (EREFUSED != ECONNREFUSED))
557     case EREFUSED: return "EREFUSED";
558 #endif
559 #ifdef EREMCHG
560     case EREMCHG: return "remote address changed";
561 #endif
562 #ifdef EREMDEV
563     case EREMDEV: return "remote device";
564 #endif
565 #ifdef EREMOTE
566     case EREMOTE: return "pathname hit remote file system";
567 #endif
568 #ifdef EREMOTEIO
569     case EREMOTEIO: return "remote i/o error";
570 #endif
571 #ifdef EREMOTERELEASE
572     case EREMOTERELEASE: return "EREMOTERELEASE";
573 #endif
574 #ifdef EROFS
575     case EROFS: return "read-only file system";
576 #endif
577 #ifdef ERPCMISMATCH
578     case ERPCMISMATCH: return "RPC version is wrong";
579 #endif
580 #ifdef ERREMOTE
581     case ERREMOTE: return "object is remote";
582 #endif
583 #ifdef ESHUTDOWN
584     case ESHUTDOWN: return "can't send afer socket shutdown";
585 #endif
586 #ifdef ESOCKTNOSUPPORT
587     case ESOCKTNOSUPPORT: return "socket type not supported";
588 #endif
589 #ifdef ESPIPE
590     case ESPIPE: return "invalid seek";
591 #endif
592 #ifdef ESRCH
593     case ESRCH: return "no such process";
594 #endif
595 #ifdef ESRMNT
596     case ESRMNT: return "srmount error";
597 #endif
598 #ifdef ESTALE
599     case ESTALE: return "stale remote file handle";
600 #endif
601 #ifdef ESUCCESS
602     case ESUCCESS: return "Error 0";
603 #endif
604 #ifdef ETIME
605     case ETIME: return "timer expired";
606 #endif
607 #ifdef ETIMEDOUT
608     case ETIMEDOUT: return "connection timed out";
609 #endif
610 #ifdef ETOOMANYREFS
611     case ETOOMANYREFS: return "too many references: can't splice";
612 #endif
613 #ifdef ETXTBSY
614     case ETXTBSY: return "text file or pseudo-device busy";
615 #endif
616 #ifdef EUCLEAN
617     case EUCLEAN: return "structure needs cleaning";
618 #endif
619 #ifdef EUNATCH
620     case EUNATCH: return "protocol driver not attached";
621 #endif
622 #ifdef EUSERS
623     case EUSERS: return "too many users";
624 #endif
625 #ifdef EVERSION
626     case EVERSION: return "version mismatch";
627 #endif
628 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
629     case EWOULDBLOCK: return "operation would block";
630 #endif
631 #ifdef EXDEV
632     case EXDEV: return "cross-domain link";
633 #endif
634 #ifdef EXFULL
635     case EXFULL: return "message tables full";
636 #endif
637     }
638 #else /* NO_SYS_ERRLIST */
639   extern int sys_nerr;
640   extern char *sys_errlist[];
641
642   if ((errnum > 0) && (errnum <= sys_nerr))
643     return sys_errlist [errnum];
644 #endif /* NO_SYS_ERRLIST */
645
646   msg = g_static_private_get (&msg_private);
647   if( !msg )
648     {
649       msg = g_new( gchar, 64 );
650       g_static_private_set (&msg_private, msg, g_free);
651     }
652
653   sprintf (msg, "unknown error (%d)", errnum);
654   return msg;
655 }
656
657 gchar*
658 g_strsignal (gint signum)
659 {
660   static GStaticPrivate msg_private = G_STATIC_PRIVATE_INIT;
661   char *msg;
662
663 #ifdef HAVE_STRSIGNAL
664   extern char *strsignal (int sig);
665   return strsignal (signum);
666 #elif NO_SYS_SIGLIST
667   switch (signum)
668     {
669 #ifdef SIGHUP
670     case SIGHUP: return "Hangup";
671 #endif
672 #ifdef SIGINT
673     case SIGINT: return "Interrupt";
674 #endif
675 #ifdef SIGQUIT
676     case SIGQUIT: return "Quit";
677 #endif
678 #ifdef SIGILL
679     case SIGILL: return "Illegal instruction";
680 #endif
681 #ifdef SIGTRAP
682     case SIGTRAP: return "Trace/breakpoint trap";
683 #endif
684 #ifdef SIGABRT
685     case SIGABRT: return "IOT trap/Abort";
686 #endif
687 #ifdef SIGBUS
688     case SIGBUS: return "Bus error";
689 #endif
690 #ifdef SIGFPE
691     case SIGFPE: return "Floating point exception";
692 #endif
693 #ifdef SIGKILL
694     case SIGKILL: return "Killed";
695 #endif
696 #ifdef SIGUSR1
697     case SIGUSR1: return "User defined signal 1";
698 #endif
699 #ifdef SIGSEGV
700     case SIGSEGV: return "Segmentation fault";
701 #endif
702 #ifdef SIGUSR2
703     case SIGUSR2: return "User defined signal 2";
704 #endif
705 #ifdef SIGPIPE
706     case SIGPIPE: return "Broken pipe";
707 #endif
708 #ifdef SIGALRM
709     case SIGALRM: return "Alarm clock";
710 #endif
711 #ifdef SIGTERM
712     case SIGTERM: return "Terminated";
713 #endif
714 #ifdef SIGSTKFLT
715     case SIGSTKFLT: return "Stack fault";
716 #endif
717 #ifdef SIGCHLD
718     case SIGCHLD: return "Child exited";
719 #endif
720 #ifdef SIGCONT
721     case SIGCONT: return "Continued";
722 #endif
723 #ifdef SIGSTOP
724     case SIGSTOP: return "Stopped (signal)";
725 #endif
726 #ifdef SIGTSTP
727     case SIGTSTP: return "Stopped";
728 #endif
729 #ifdef SIGTTIN
730     case SIGTTIN: return "Stopped (tty input)";
731 #endif
732 #ifdef SIGTTOU
733     case SIGTTOU: return "Stopped (tty output)";
734 #endif
735 #ifdef SIGURG
736     case SIGURG: return "Urgent condition";
737 #endif
738 #ifdef SIGXCPU
739     case SIGXCPU: return "CPU time limit exceeded";
740 #endif
741 #ifdef SIGXFSZ
742     case SIGXFSZ: return "File size limit exceeded";
743 #endif
744 #ifdef SIGVTALRM
745     case SIGVTALRM: return "Virtual time alarm";
746 #endif
747 #ifdef SIGPROF
748     case SIGPROF: return "Profile signal";
749 #endif
750 #ifdef SIGWINCH
751     case SIGWINCH: return "Window size changed";
752 #endif
753 #ifdef SIGIO
754     case SIGIO: return "Possible I/O";
755 #endif
756 #ifdef SIGPWR
757     case SIGPWR: return "Power failure";
758 #endif
759 #ifdef SIGUNUSED
760     case SIGUNUSED: return "Unused signal";
761 #endif
762     }
763 #else /* NO_SYS_SIGLIST */
764
765 #ifndef NO_SYS_SIGLIST_DECL
766   /*(see Tue Jan 19 00:44:24 1999 in changelog)*/
767   extern char *sys_siglist[];
768 #endif
769
770   return (char*) /* this function should return const --josh */ sys_siglist [signum];
771 #endif /* NO_SYS_SIGLIST */
772
773   msg = g_static_private_get (&msg_private);
774   if( !msg )
775     {
776       msg = g_new( gchar, 64 );
777       g_static_private_set (&msg_private, msg, g_free);
778     }
779
780   sprintf (msg, "unknown signal (%d)", signum);
781   return msg;
782 }
783
784 guint
785 g_printf_string_upper_bound (const gchar* format,
786                              va_list      args)
787 {
788   guint len = 1;
789
790   while (*format)
791     {
792       gboolean long_int = FALSE;
793       gboolean extra_long = FALSE;
794       gchar c;
795
796       c = *format++;
797
798       if (c == '%')
799         {
800           gboolean done = FALSE;
801
802           while (*format && !done)
803             {
804               switch (*format++)
805                 {
806                   gchar *string_arg;
807
808                 case '*':
809                   len += va_arg (args, int);
810                   break;
811                 case '1':
812                 case '2':
813                 case '3':
814                 case '4':
815                 case '5':
816                 case '6':
817                 case '7':
818                 case '8':
819                 case '9':
820                   /* add specified format length, since it might exceed the
821                    * size we assume it to have.
822                    */
823                   format -= 1;
824                   len += strtol (format, (char**) &format, 10);
825                   break;
826                 case 'h':
827                   /* ignore short int flag, since all args have at least the
828                    * same size as an int
829                    */
830                   break;
831                 case 'l':
832                   if (long_int)
833                     extra_long = TRUE; /* linux specific */
834                   else
835                     long_int = TRUE;
836                   break;
837                 case 'q':
838                 case 'L':
839                   long_int = TRUE;
840                   extra_long = TRUE;
841                   break;
842                 case 's':
843                   string_arg = va_arg (args, char *);
844                   if (string_arg)
845                     len += strlen (string_arg);
846                   else
847                     {
848                       /* add enough padding to hold "(null)" identifier */
849                       len += 16;
850                     }
851                   done = TRUE;
852                   break;
853                 case 'd':
854                 case 'i':
855                 case 'o':
856                 case 'u':
857                 case 'x':
858                 case 'X':
859 #ifdef  G_HAVE_GINT64
860                   if (extra_long)
861                     (void) va_arg (args, gint64);
862                   else
863 #endif  /* G_HAVE_GINT64 */
864                     {
865                       if (long_int)
866                         (void) va_arg (args, long);
867                       else
868                         (void) va_arg (args, int);
869                     }
870                   len += extra_long ? 64 : 32;
871                   done = TRUE;
872                   break;
873                 case 'D':
874                 case 'O':
875                 case 'U':
876                   (void) va_arg (args, long);
877                   len += 32;
878                   done = TRUE;
879                   break;
880                 case 'e':
881                 case 'E':
882                 case 'f':
883                 case 'g':
884 #ifdef HAVE_LONG_DOUBLE
885                   if (extra_long)
886                     (void) va_arg (args, long double);
887                   else
888 #endif  /* HAVE_LONG_DOUBLE */
889                     (void) va_arg (args, double);
890                   len += extra_long ? 64 : 32;
891                   done = TRUE;
892                   break;
893                 case 'c':
894                   (void) va_arg (args, int);
895                   len += 1;
896                   done = TRUE;
897                   break;
898                 case 'p':
899                 case 'n':
900                   (void) va_arg (args, void*);
901                   len += 32;
902                   done = TRUE;
903                   break;
904                 case '%':
905                   len += 1;
906                   done = TRUE;
907                   break;
908                 default:
909                   /* ignore unknow/invalid flags */
910                   break;
911                 }
912             }
913         }
914       else
915         len += 1;
916     }
917
918   return len;
919 }
920
921 void
922 g_strdown (gchar  *string)
923 {
924   register gchar *s;
925
926   g_return_if_fail (string != NULL);
927
928   s = string;
929
930   while (*s)
931     {
932       *s = tolower (*s);
933       s++;
934     }
935 }
936
937 void
938 g_strup (gchar  *string)
939 {
940   register gchar *s;
941
942   g_return_if_fail (string != NULL);
943
944   s = string;
945
946   while (*s)
947     {
948       *s = toupper (*s);
949       s++;
950     }
951 }
952
953 void
954 g_strreverse (gchar       *string)
955 {
956   g_return_if_fail (string != NULL);
957
958   if (*string)
959     {
960       register gchar *h, *t;
961
962       h = string;
963       t = string + strlen (string) - 1;
964
965       while (h < t)
966         {
967           register gchar c;
968
969           c = *h;
970           *h = *t;
971           h++;
972           *t = c;
973           t--;
974         }
975     }
976 }
977
978 gint
979 g_strcasecmp (const gchar *s1,
980               const gchar *s2)
981 {
982 #ifdef HAVE_STRCASECMP
983   return strcasecmp (s1, s2);
984 #else
985   gint c1, c2;
986
987   g_return_val_if_fail (s1 != NULL, 0);
988   g_return_val_if_fail (s2 != NULL, 0);
989
990   while (*s1 && *s2)
991     {
992       /* According to A. Cox, some platforms have islower's that
993        * don't work right on non-uppercase
994        */
995       c1 = isupper ((guchar)*s1) ? tolower ((guchar)*s1) : *s1;
996       c2 = isupper ((guchar)*s2) ? tolower ((guchar)*s2) : *s2;
997       if (c1 != c2)
998         return (c1 - c2);
999       s1++; s2++;
1000     }
1001
1002   return (((gint)(guchar) *s1) - ((gint)(guchar) *s2));
1003 #endif
1004 }
1005
1006 gint
1007 g_strncasecmp (const gchar *s1,
1008                const gchar *s2,
1009                guint n)
1010 {
1011 #ifdef HAVE_STRNCASECMP
1012   return strncasecmp (s1, s2, n);
1013 #else
1014   gint c1, c2;
1015
1016   g_return_val_if_fail (s1 != NULL, 0);
1017   g_return_val_if_fail (s2 != NULL, 0);
1018
1019   while (n-- && *s1 && *s2)
1020     {
1021       /* According to A. Cox, some platforms have islower's that
1022        * don't work right on non-uppercase
1023        */
1024       c1 = isupper ((guchar)*s1) ? tolower ((guchar)*s1) : *s1;
1025       c2 = isupper ((guchar)*s2) ? tolower ((guchar)*s2) : *s2;
1026       if (c1 != c2)
1027         return (c1 - c2);
1028       s1++; s2++;
1029     }
1030
1031   if (n)
1032     return (((gint)(guchar) *s1) - ((gint)(guchar) *s2));
1033   else
1034     return 0;
1035 #endif
1036 }
1037
1038 gchar*
1039 g_strdelimit (gchar       *string,
1040               const gchar *delimiters,
1041               gchar        new_delim)
1042 {
1043   register gchar *c;
1044
1045   g_return_val_if_fail (string != NULL, NULL);
1046
1047   if (!delimiters)
1048     delimiters = G_STR_DELIMITERS;
1049
1050   for (c = string; *c; c++)
1051     {
1052       if (strchr (delimiters, *c))
1053         *c = new_delim;
1054     }
1055
1056   return string;
1057 }
1058
1059 gchar*
1060 g_strescape (gchar *string)
1061 {
1062   gchar *q;
1063   gchar *escaped;
1064   guint backslashes = 0;
1065   gchar *p = string;
1066
1067   g_return_val_if_fail (string != NULL, NULL);
1068
1069   while (*p != '\000')
1070     backslashes += (*p++ == '\\');
1071
1072   if (!backslashes)
1073     return g_strdup (string);
1074
1075   escaped = g_new (gchar, strlen (string) + backslashes + 1);
1076
1077   p = string;
1078   q = escaped;
1079
1080   while (*p != '\000')
1081     {
1082       if (*p == '\\')
1083         *q++ = '\\';
1084       *q++ = *p++;
1085     }
1086   *q = '\000';
1087
1088   return escaped;
1089 }
1090
1091 /* blame Elliot for these next five routines */
1092 gchar*
1093 g_strchug (gchar *string)
1094 {
1095   gchar *start;
1096
1097   g_return_val_if_fail (string != NULL, NULL);
1098
1099   for (start = string; *start && isspace (*start); start++)
1100     ;
1101
1102   strcpy (string, start);
1103
1104   return string;
1105 }
1106
1107 gchar*
1108 g_strchomp (gchar *string)
1109 {
1110   gchar *s;
1111
1112   g_return_val_if_fail (string != NULL, NULL);
1113
1114   if (!*string)
1115     return string;
1116
1117   for (s = string + strlen (string) - 1; s >= string && isspace (*s); s--)
1118     *s = '\0';
1119
1120   return string;
1121 }
1122
1123 gchar**
1124 g_strsplit (const gchar *string,
1125             const gchar *delimiter,
1126             gint         max_tokens)
1127 {
1128   GSList *string_list = NULL, *slist;
1129   gchar **str_array, *s;
1130   guint i, n = 1;
1131
1132   g_return_val_if_fail (string != NULL, NULL);
1133   g_return_val_if_fail (delimiter != NULL, NULL);
1134
1135   if (max_tokens < 1)
1136     max_tokens = G_MAXINT;
1137
1138   s = strstr (string, delimiter);
1139   if (s)
1140     {
1141       guint delimiter_len = strlen (delimiter);
1142
1143       do
1144         {
1145           guint len;
1146           gchar *new_string;
1147
1148           len = s - string;
1149           new_string = g_new (gchar, len + 1);
1150           strncpy (new_string, string, len);
1151           new_string[len] = 0;
1152           string_list = g_slist_prepend (string_list, new_string);
1153           n++;
1154           string = s + delimiter_len;
1155           s = strstr (string, delimiter);
1156         }
1157       while (--max_tokens && s);
1158     }
1159   if (*string)
1160     {
1161       n++;
1162       string_list = g_slist_prepend (string_list, g_strdup (string));
1163     }
1164
1165   str_array = g_new (gchar*, n);
1166
1167   i = n - 1;
1168
1169   str_array[i--] = NULL;
1170   for (slist = string_list; slist; slist = slist->next)
1171     str_array[i--] = slist->data;
1172
1173   g_slist_free (string_list);
1174
1175   return str_array;
1176 }
1177
1178 void
1179 g_strfreev (gchar **str_array)
1180 {
1181   if (str_array)
1182     {
1183       int i;
1184
1185       for(i = 0; str_array[i] != NULL; i++)
1186         g_free(str_array[i]);
1187
1188       g_free (str_array);
1189     }
1190 }
1191
1192 gchar*
1193 g_strjoinv (const gchar  *separator,
1194             gchar       **str_array)
1195 {
1196   gchar *string;
1197
1198   g_return_val_if_fail (str_array != NULL, NULL);
1199
1200   if(separator == NULL)
1201     separator = "";
1202
1203   if (*str_array)
1204     {
1205       guint i, len;
1206       guint separator_len;
1207
1208       separator_len = strlen (separator);
1209       len = 1 + strlen (str_array[0]);
1210       for(i = 1; str_array[i] != NULL; i++)
1211         len += separator_len + strlen(str_array[i]);
1212
1213       string = g_new (gchar, len);
1214       *string = 0;
1215       strcat (string, *str_array);
1216       for (i = 1; str_array[i] != NULL; i++)
1217         {
1218           strcat (string, separator);
1219           strcat (string, str_array[i]);
1220         }
1221       }
1222   else
1223     string = g_strdup ("");
1224
1225   return string;
1226 }
1227
1228 gchar*
1229 g_strjoin (const gchar  *separator,
1230            ...)
1231 {
1232   gchar *string, *s;
1233   va_list args;
1234   guint len;
1235   guint separator_len;
1236
1237   if(separator == NULL)
1238     separator = "";
1239
1240   separator_len = strlen (separator);
1241
1242   va_start(args, separator);
1243
1244   s = va_arg(args, gchar *);
1245
1246   if(s) {
1247     len = strlen(s) + 1;
1248
1249     while((s = va_arg(args, gchar*)))
1250       {
1251         len += separator_len + strlen(s);
1252       }
1253     va_end(args);
1254
1255     string = g_new (gchar, len);
1256
1257     va_start(args, separator);
1258
1259     *string = 0;
1260     s = va_arg(args, gchar*);
1261     strcat (string, s);
1262
1263     while((s = va_arg(args, gchar*)))
1264       {
1265         strcat(string, separator);
1266         strcat(string, s);
1267       }
1268
1269   } else
1270     string = g_strdup("");
1271
1272   va_end(args);
1273
1274   return string;
1275 }