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