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