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