source: trunk/third/glib/gstrfuncs.c @ 15778

Revision 15778, 34.7 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r15777, which included commits to RCS files with non-trunk default branches.
Line 
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
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
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}
Note: See TracBrowser for help on using the repository browser.