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