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