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