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