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