mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-23 18:52:09 +01:00
Backport implementation of g_printf_string_upper_bound from 1.3. Bug
Mon Feb 26 21:06:17 CST 2001 Shawn T. Amundson <amundson@gtk.org> * gstrfuncs.c: Backport implementation of g_printf_string_upper_bound from 1.3. Bug #50217. * gmain.c: Cast RHS of an assignment to a GSourceFunc variable. Fourth param of g_source_add() is a gpointer, so add a cast to that param. From Richard K. Lloyd. A portion of bug #50793.
This commit is contained in:
parent
80af227458
commit
a44d5145ea
10
ChangeLog
10
ChangeLog
@ -1,3 +1,13 @@
|
|||||||
|
|
||||||
|
Mon Feb 26 21:06:17 CST 2001 Shawn T. Amundson <amundson@gtk.org>
|
||||||
|
|
||||||
|
* gstrfuncs.c: Backport implementation of
|
||||||
|
g_printf_string_upper_bound from 1.3. Bug #50217.
|
||||||
|
|
||||||
|
* gmain.c: Cast RHS of an assignment to a GSourceFunc variable.
|
||||||
|
Fourth param of g_source_add() is a gpointer, so add a cast to that
|
||||||
|
param. From Richard K. Lloyd. A portion of bug #50793.
|
||||||
|
|
||||||
Mon Feb 26 23:06:54 2001 Owen Taylor <otaylor@redhat.com>
|
Mon Feb 26 23:06:54 2001 Owen Taylor <otaylor@redhat.com>
|
||||||
|
|
||||||
* README: Fix information about reporting bugs to
|
* README: Fix information about reporting bugs to
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
|
||||||
|
Mon Feb 26 21:06:17 CST 2001 Shawn T. Amundson <amundson@gtk.org>
|
||||||
|
|
||||||
|
* gstrfuncs.c: Backport implementation of
|
||||||
|
g_printf_string_upper_bound from 1.3. Bug #50217.
|
||||||
|
|
||||||
|
* gmain.c: Cast RHS of an assignment to a GSourceFunc variable.
|
||||||
|
Fourth param of g_source_add() is a gpointer, so add a cast to that
|
||||||
|
param. From Richard K. Lloyd. A portion of bug #50793.
|
||||||
|
|
||||||
Mon Feb 26 23:06:54 2001 Owen Taylor <otaylor@redhat.com>
|
Mon Feb 26 23:06:54 2001 Owen Taylor <otaylor@redhat.com>
|
||||||
|
|
||||||
* README: Fix information about reporting bugs to
|
* README: Fix information about reporting bugs to
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
|
||||||
|
Mon Feb 26 21:06:17 CST 2001 Shawn T. Amundson <amundson@gtk.org>
|
||||||
|
|
||||||
|
* gstrfuncs.c: Backport implementation of
|
||||||
|
g_printf_string_upper_bound from 1.3. Bug #50217.
|
||||||
|
|
||||||
|
* gmain.c: Cast RHS of an assignment to a GSourceFunc variable.
|
||||||
|
Fourth param of g_source_add() is a gpointer, so add a cast to that
|
||||||
|
param. From Richard K. Lloyd. A portion of bug #50793.
|
||||||
|
|
||||||
Mon Feb 26 23:06:54 2001 Owen Taylor <otaylor@redhat.com>
|
Mon Feb 26 23:06:54 2001 Owen Taylor <otaylor@redhat.com>
|
||||||
|
|
||||||
* README: Fix information about reporting bugs to
|
* README: Fix information about reporting bugs to
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
|
||||||
|
Mon Feb 26 21:06:17 CST 2001 Shawn T. Amundson <amundson@gtk.org>
|
||||||
|
|
||||||
|
* gstrfuncs.c: Backport implementation of
|
||||||
|
g_printf_string_upper_bound from 1.3. Bug #50217.
|
||||||
|
|
||||||
|
* gmain.c: Cast RHS of an assignment to a GSourceFunc variable.
|
||||||
|
Fourth param of g_source_add() is a gpointer, so add a cast to that
|
||||||
|
param. From Richard K. Lloyd. A portion of bug #50793.
|
||||||
|
|
||||||
Mon Feb 26 23:06:54 2001 Owen Taylor <otaylor@redhat.com>
|
Mon Feb 26 23:06:54 2001 Owen Taylor <otaylor@redhat.com>
|
||||||
|
|
||||||
* README: Fix information about reporting bugs to
|
* README: Fix information about reporting bugs to
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
|
||||||
|
Mon Feb 26 21:06:17 CST 2001 Shawn T. Amundson <amundson@gtk.org>
|
||||||
|
|
||||||
|
* gstrfuncs.c: Backport implementation of
|
||||||
|
g_printf_string_upper_bound from 1.3. Bug #50217.
|
||||||
|
|
||||||
|
* gmain.c: Cast RHS of an assignment to a GSourceFunc variable.
|
||||||
|
Fourth param of g_source_add() is a gpointer, so add a cast to that
|
||||||
|
param. From Richard K. Lloyd. A portion of bug #50793.
|
||||||
|
|
||||||
Mon Feb 26 23:06:54 2001 Owen Taylor <otaylor@redhat.com>
|
Mon Feb 26 23:06:54 2001 Owen Taylor <otaylor@redhat.com>
|
||||||
|
|
||||||
* README: Fix information about reporting bugs to
|
* README: Fix information about reporting bugs to
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
|
||||||
|
Mon Feb 26 21:06:17 CST 2001 Shawn T. Amundson <amundson@gtk.org>
|
||||||
|
|
||||||
|
* gstrfuncs.c: Backport implementation of
|
||||||
|
g_printf_string_upper_bound from 1.3. Bug #50217.
|
||||||
|
|
||||||
|
* gmain.c: Cast RHS of an assignment to a GSourceFunc variable.
|
||||||
|
Fourth param of g_source_add() is a gpointer, so add a cast to that
|
||||||
|
param. From Richard K. Lloyd. A portion of bug #50793.
|
||||||
|
|
||||||
Mon Feb 26 23:06:54 2001 Owen Taylor <otaylor@redhat.com>
|
Mon Feb 26 23:06:54 2001 Owen Taylor <otaylor@redhat.com>
|
||||||
|
|
||||||
* README: Fix information about reporting bugs to
|
* README: Fix information about reporting bugs to
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
|
||||||
|
Mon Feb 26 21:06:17 CST 2001 Shawn T. Amundson <amundson@gtk.org>
|
||||||
|
|
||||||
|
* gstrfuncs.c: Backport implementation of
|
||||||
|
g_printf_string_upper_bound from 1.3. Bug #50217.
|
||||||
|
|
||||||
|
* gmain.c: Cast RHS of an assignment to a GSourceFunc variable.
|
||||||
|
Fourth param of g_source_add() is a gpointer, so add a cast to that
|
||||||
|
param. From Richard K. Lloyd. A portion of bug #50793.
|
||||||
|
|
||||||
Mon Feb 26 23:06:54 2001 Owen Taylor <otaylor@redhat.com>
|
Mon Feb 26 23:06:54 2001 Owen Taylor <otaylor@redhat.com>
|
||||||
|
|
||||||
* README: Fix information about reporting bugs to
|
* README: Fix information about reporting bugs to
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
|
||||||
|
Mon Feb 26 21:06:17 CST 2001 Shawn T. Amundson <amundson@gtk.org>
|
||||||
|
|
||||||
|
* gstrfuncs.c: Backport implementation of
|
||||||
|
g_printf_string_upper_bound from 1.3. Bug #50217.
|
||||||
|
|
||||||
|
* gmain.c: Cast RHS of an assignment to a GSourceFunc variable.
|
||||||
|
Fourth param of g_source_add() is a gpointer, so add a cast to that
|
||||||
|
param. From Richard K. Lloyd. A portion of bug #50793.
|
||||||
|
|
||||||
Mon Feb 26 23:06:54 2001 Owen Taylor <otaylor@redhat.com>
|
Mon Feb 26 23:06:54 2001 Owen Taylor <otaylor@redhat.com>
|
||||||
|
|
||||||
* README: Fix information about reporting bugs to
|
* README: Fix information about reporting bugs to
|
||||||
|
@ -1362,7 +1362,7 @@ g_idle_dispatch (gpointer source_data,
|
|||||||
GTimeVal *dispatch_time,
|
GTimeVal *dispatch_time,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GSourceFunc func = source_data;
|
GSourceFunc func = (GSourceFunc) source_data;
|
||||||
|
|
||||||
return func (user_data);
|
return func (user_data);
|
||||||
}
|
}
|
||||||
@ -1375,7 +1375,7 @@ g_idle_add_full (gint priority,
|
|||||||
{
|
{
|
||||||
g_return_val_if_fail (function != NULL, 0);
|
g_return_val_if_fail (function != NULL, 0);
|
||||||
|
|
||||||
return g_source_add (priority, FALSE, &idle_funcs, function, data, notify);
|
return g_source_add (priority, FALSE, &idle_funcs, (gpointer) function, data, notify);
|
||||||
}
|
}
|
||||||
|
|
||||||
guint
|
guint
|
||||||
|
359
glib/gstrfuncs.c
359
glib/gstrfuncs.c
@ -37,6 +37,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <ctype.h> /* For tolower() */
|
#include <ctype.h> /* For tolower() */
|
||||||
#if !defined (HAVE_STRSIGNAL) || !defined(NO_SYS_SIGLIST_DECL)
|
#if !defined (HAVE_STRSIGNAL) || !defined(NO_SYS_SIGLIST_DECL)
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@ -46,6 +47,36 @@
|
|||||||
* inteferes with g_strsignal() on some OSes
|
* inteferes with g_strsignal() on some OSes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
typedef union _GDoubleIEEE754 GDoubleIEEE754;
|
||||||
|
#define G_IEEE754_DOUBLE_BIAS (1023)
|
||||||
|
/* multiply with base2 exponent to get base10 exponent (nomal numbers) */
|
||||||
|
#define G_LOG_2_BASE_10 (0.30102999566398119521)
|
||||||
|
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||||
|
union _GDoubleIEEE754
|
||||||
|
{
|
||||||
|
gdouble v_double;
|
||||||
|
struct {
|
||||||
|
guint mantissa_low : 32;
|
||||||
|
guint mantissa_high : 20;
|
||||||
|
guint biased_exponent : 11;
|
||||||
|
guint sign : 1;
|
||||||
|
} mpn;
|
||||||
|
};
|
||||||
|
#elif G_BYTE_ORDER == G_BIG_ENDIAN
|
||||||
|
union _GDoubleIEEE754
|
||||||
|
{
|
||||||
|
gdouble v_double;
|
||||||
|
struct {
|
||||||
|
guint sign : 1;
|
||||||
|
guint biased_exponent : 11;
|
||||||
|
guint mantissa_high : 20;
|
||||||
|
guint mantissa_low : 32;
|
||||||
|
} mpn;
|
||||||
|
};
|
||||||
|
#else /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
|
||||||
|
#error unknown ENDIAN type
|
||||||
|
#endif /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
|
||||||
|
|
||||||
gchar*
|
gchar*
|
||||||
g_strdup (const gchar *str)
|
g_strdup (const gchar *str)
|
||||||
{
|
{
|
||||||
@ -791,32 +822,81 @@ g_strsignal (gint signum)
|
|||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
guint min_width;
|
||||||
|
guint precision;
|
||||||
|
gboolean alternate_format, zero_padding, adjust_left, locale_grouping;
|
||||||
|
gboolean add_space, add_sign, possible_sign, seen_precision;
|
||||||
|
gboolean mod_half, mod_long, mod_extra_long;
|
||||||
|
} PrintfArgSpec;
|
||||||
|
|
||||||
guint
|
guint
|
||||||
g_printf_string_upper_bound (const gchar* format,
|
g_printf_string_upper_bound (const gchar* format,
|
||||||
va_list args)
|
va_list args)
|
||||||
{
|
{
|
||||||
|
static const gboolean honour_longs = SIZEOF_LONG > 4 || SIZEOF_VOID_P > 4;
|
||||||
guint len = 1;
|
guint len = 1;
|
||||||
|
|
||||||
|
if (!format)
|
||||||
|
return len;
|
||||||
|
|
||||||
while (*format)
|
while (*format)
|
||||||
{
|
{
|
||||||
gboolean long_int = FALSE;
|
register gchar c = *format++;
|
||||||
gboolean extra_long = FALSE;
|
|
||||||
gchar c;
|
|
||||||
|
|
||||||
|
if (c != '%')
|
||||||
|
len += 1;
|
||||||
|
else /* (c == '%') */
|
||||||
|
{
|
||||||
|
PrintfArgSpec spec = { 0, };
|
||||||
|
gboolean seen_l = FALSE, conv_done = FALSE;
|
||||||
|
guint conv_len = 0;
|
||||||
|
const gchar *spec_start = format;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
c = *format++;
|
c = *format++;
|
||||||
|
switch (c)
|
||||||
if (c == '%')
|
|
||||||
{
|
{
|
||||||
gboolean done = FALSE;
|
GDoubleIEEE754 u_double;
|
||||||
|
guint v_uint;
|
||||||
|
gint v_int;
|
||||||
|
const gchar *v_string;
|
||||||
|
|
||||||
while (*format && !done)
|
/* beware of positional parameters
|
||||||
{
|
*/
|
||||||
switch (*format++)
|
case '$':
|
||||||
{
|
g_warning (G_GNUC_PRETTY_FUNCTION
|
||||||
gchar *string_arg;
|
"(): unable to handle positional parameters (%%n$)");
|
||||||
|
len += 1024; /* try adding some safety padding */
|
||||||
|
break;
|
||||||
|
|
||||||
case '*':
|
/* parse flags
|
||||||
len += va_arg (args, int);
|
*/
|
||||||
|
case '#':
|
||||||
|
spec.alternate_format = TRUE;
|
||||||
|
break;
|
||||||
|
case '0':
|
||||||
|
spec.zero_padding = TRUE;
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
spec.adjust_left = TRUE;
|
||||||
|
break;
|
||||||
|
case ' ':
|
||||||
|
spec.add_space = TRUE;
|
||||||
|
break;
|
||||||
|
case '+':
|
||||||
|
spec.add_sign = TRUE;
|
||||||
|
break;
|
||||||
|
case '\'':
|
||||||
|
spec.locale_grouping = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* parse output size specifications
|
||||||
|
*/
|
||||||
|
case '.':
|
||||||
|
spec.seen_precision = TRUE;
|
||||||
break;
|
break;
|
||||||
case '1':
|
case '1':
|
||||||
case '2':
|
case '2':
|
||||||
@ -827,107 +907,224 @@ g_printf_string_upper_bound (const gchar* format,
|
|||||||
case '7':
|
case '7':
|
||||||
case '8':
|
case '8':
|
||||||
case '9':
|
case '9':
|
||||||
/* add specified format length, since it might exceed the
|
v_uint = c - '0';
|
||||||
* size we assume it to have.
|
c = *format;
|
||||||
*/
|
while (c >= '0' && c <= '9')
|
||||||
format -= 1;
|
{
|
||||||
len += strtol (format, (char**) &format, 10);
|
format++;
|
||||||
|
v_uint = v_uint * 10 + c - '0';
|
||||||
|
c = *format;
|
||||||
|
}
|
||||||
|
if (spec.seen_precision)
|
||||||
|
spec.precision = MAX (spec.precision, v_uint);
|
||||||
|
else
|
||||||
|
spec.min_width = MAX (spec.min_width, v_uint);
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case '*':
|
||||||
/* ignore short int flag, since all args have at least the
|
v_int = va_arg (args, int);
|
||||||
* same size as an int
|
if (spec.seen_precision)
|
||||||
|
{
|
||||||
|
/* forget about negative precision */
|
||||||
|
if (v_int >= 0)
|
||||||
|
spec.precision = MAX (spec.precision, v_int);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (v_int < 0)
|
||||||
|
{
|
||||||
|
v_int = - v_int;
|
||||||
|
spec.adjust_left = TRUE;
|
||||||
|
}
|
||||||
|
spec.min_width = MAX (spec.min_width, v_int);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* parse type modifiers
|
||||||
*/
|
*/
|
||||||
|
case 'h':
|
||||||
|
spec.mod_half = TRUE;
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
if (long_int)
|
if (!seen_l)
|
||||||
extra_long = TRUE; /* linux specific */
|
|
||||||
else
|
|
||||||
long_int = TRUE;
|
|
||||||
break;
|
|
||||||
case 'q':
|
|
||||||
case 'L':
|
|
||||||
long_int = TRUE;
|
|
||||||
extra_long = TRUE;
|
|
||||||
break;
|
|
||||||
case '\'':
|
|
||||||
len += 64;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
string_arg = va_arg (args, char *);
|
|
||||||
if (string_arg)
|
|
||||||
len += strlen (string_arg);
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* add enough padding to hold "(null)" identifier */
|
spec.mod_long = TRUE;
|
||||||
len += 16;
|
seen_l = TRUE;
|
||||||
}
|
|
||||||
done = TRUE;
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
/* else, fall through */
|
||||||
|
case 'L':
|
||||||
|
case 'q':
|
||||||
|
spec.mod_long = TRUE;
|
||||||
|
spec.mod_extra_long = TRUE;
|
||||||
|
break;
|
||||||
|
case 'z':
|
||||||
|
case 'Z':
|
||||||
|
#if GLIB_SIZEOF_SIZE_T > 4
|
||||||
|
spec.mod_long = TRUE;
|
||||||
|
spec.mod_extra_long = TRUE;
|
||||||
|
#endif /* GLIB_SIZEOF_SIZE_T > 4 */
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
#if GLIB_SIZEOF_PTRDIFF_T > 4
|
||||||
|
spec.mod_long = TRUE;
|
||||||
|
spec.mod_extra_long = TRUE;
|
||||||
|
#endif /* GLIB_SIZEOF_PTRDIFF_T > 4 */
|
||||||
|
break;
|
||||||
|
case 'j':
|
||||||
|
#if GLIB_SIZEOF_INTMAX_T > 4
|
||||||
|
spec.mod_long = TRUE;
|
||||||
|
spec.mod_extra_long = TRUE;
|
||||||
|
#endif /* GLIB_SIZEOF_INTMAX_T > 4 */
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* parse output conversions
|
||||||
|
*/
|
||||||
|
case '%':
|
||||||
|
conv_len += 1;
|
||||||
|
break;
|
||||||
|
case 'O':
|
||||||
|
case 'D':
|
||||||
|
case 'I':
|
||||||
|
case 'U':
|
||||||
|
/* some C libraries feature long variants for these as well? */
|
||||||
|
spec.mod_long = TRUE;
|
||||||
|
/* fall through */
|
||||||
|
case 'o':
|
||||||
|
conv_len += 2;
|
||||||
|
/* fall through */
|
||||||
case 'd':
|
case 'd':
|
||||||
case 'i':
|
case 'i':
|
||||||
case 'o':
|
conv_len += 1; /* sign */
|
||||||
|
/* fall through */
|
||||||
case 'u':
|
case 'u':
|
||||||
|
conv_len += 4;
|
||||||
|
/* fall through */
|
||||||
case 'x':
|
case 'x':
|
||||||
case 'X':
|
case 'X':
|
||||||
#ifdef G_HAVE_GINT64
|
spec.possible_sign = TRUE;
|
||||||
if (extra_long)
|
conv_len += 10;
|
||||||
(void) va_arg (args, gint64);
|
if (spec.mod_long && honour_longs)
|
||||||
else
|
conv_len *= 2;
|
||||||
#endif /* G_HAVE_GINT64 */
|
if (spec.mod_extra_long)
|
||||||
|
conv_len *= 2;
|
||||||
|
if (spec.mod_extra_long)
|
||||||
{
|
{
|
||||||
if (long_int)
|
#ifdef G_HAVE_GINT64
|
||||||
|
(void) va_arg (args, gint64);
|
||||||
|
#else /* !G_HAVE_GINT64 */
|
||||||
|
(void) va_arg (args, long);
|
||||||
|
#endif /* !G_HAVE_GINT64 */
|
||||||
|
}
|
||||||
|
else if (spec.mod_long)
|
||||||
(void) va_arg (args, long);
|
(void) va_arg (args, long);
|
||||||
else
|
else
|
||||||
(void) va_arg (args, int);
|
(void) va_arg (args, int);
|
||||||
}
|
|
||||||
len += extra_long ? 64 : 32;
|
|
||||||
done = TRUE;
|
|
||||||
break;
|
|
||||||
case 'D':
|
|
||||||
case 'O':
|
|
||||||
case 'U':
|
|
||||||
(void) va_arg (args, long);
|
|
||||||
len += 32;
|
|
||||||
done = TRUE;
|
|
||||||
break;
|
break;
|
||||||
|
case 'A':
|
||||||
|
case 'a':
|
||||||
|
/* 0x */
|
||||||
|
conv_len += 2;
|
||||||
|
/* fall through */
|
||||||
|
case 'g':
|
||||||
|
case 'G':
|
||||||
case 'e':
|
case 'e':
|
||||||
case 'E':
|
case 'E':
|
||||||
case 'f':
|
case 'f':
|
||||||
case 'g':
|
spec.possible_sign = TRUE;
|
||||||
case 'G':
|
/* n . dddddddddddddddddddddddd E +- eeee */
|
||||||
|
conv_len += 1 + 1 + MAX (24, spec.precision) + 1 + 1 + 4;
|
||||||
|
if (spec.mod_extra_long)
|
||||||
|
g_warning (G_GNUC_PRETTY_FUNCTION
|
||||||
|
"(): unable to handle long double, collecting double only");
|
||||||
#ifdef HAVE_LONG_DOUBLE
|
#ifdef HAVE_LONG_DOUBLE
|
||||||
if (extra_long)
|
#error need to implement special handling for long double
|
||||||
(void) va_arg (args, long double);
|
#endif
|
||||||
else
|
u_double.v_double = va_arg (args, double);
|
||||||
#endif /* HAVE_LONG_DOUBLE */
|
/* %f can expand up to all significant digits before '.' (308) */
|
||||||
(void) va_arg (args, double);
|
if (c == 'f' &&
|
||||||
len += extra_long ? 128 : 64;
|
u_double.mpn.biased_exponent > 0 && u_double.mpn.biased_exponent < 2047)
|
||||||
done = TRUE;
|
{
|
||||||
|
gint exp = u_double.mpn.biased_exponent;
|
||||||
|
|
||||||
|
exp -= G_IEEE754_DOUBLE_BIAS;
|
||||||
|
exp = exp * G_LOG_2_BASE_10 + 1;
|
||||||
|
conv_len += exp;
|
||||||
|
}
|
||||||
|
/* some printf() implementations require extra padding for rounding */
|
||||||
|
conv_len += 2;
|
||||||
|
/* we can't really handle locale specific grouping here */
|
||||||
|
if (spec.locale_grouping)
|
||||||
|
conv_len *= 2;
|
||||||
break;
|
break;
|
||||||
|
case 'C':
|
||||||
|
spec.mod_long = TRUE;
|
||||||
|
/* fall through */
|
||||||
case 'c':
|
case 'c':
|
||||||
|
conv_len += spec.mod_long ? MB_LEN_MAX : 1;
|
||||||
(void) va_arg (args, int);
|
(void) va_arg (args, int);
|
||||||
len += 1;
|
|
||||||
done = TRUE;
|
|
||||||
break;
|
break;
|
||||||
|
case 'S':
|
||||||
|
spec.mod_long = TRUE;
|
||||||
|
/* fall through */
|
||||||
|
case 's':
|
||||||
|
v_string = va_arg (args, char*);
|
||||||
|
if (!v_string)
|
||||||
|
conv_len += 8; /* hold "(null)" */
|
||||||
|
else if (spec.seen_precision)
|
||||||
|
conv_len += spec.precision;
|
||||||
|
else
|
||||||
|
conv_len += strlen (v_string);
|
||||||
|
conv_done = TRUE;
|
||||||
|
if (spec.mod_long)
|
||||||
|
{
|
||||||
|
g_warning (G_GNUC_PRETTY_FUNCTION
|
||||||
|
"(): unable to handle wide char strings");
|
||||||
|
len += 1024; /* try adding some safety padding */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'P': /* do we actually need this? */
|
||||||
|
/* fall through */
|
||||||
case 'p':
|
case 'p':
|
||||||
|
spec.alternate_format = TRUE;
|
||||||
|
conv_len += 10;
|
||||||
|
if (honour_longs)
|
||||||
|
conv_len *= 2;
|
||||||
|
/* fall through */
|
||||||
case 'n':
|
case 'n':
|
||||||
|
conv_done = TRUE;
|
||||||
(void) va_arg (args, void*);
|
(void) va_arg (args, void*);
|
||||||
len += 32;
|
|
||||||
done = TRUE;
|
|
||||||
break;
|
break;
|
||||||
case '%':
|
case 'm':
|
||||||
len += 1;
|
/* there's not much we can do to be clever */
|
||||||
done = TRUE;
|
v_string = g_strerror (errno);
|
||||||
|
v_uint = v_string ? strlen (v_string) : 0;
|
||||||
|
conv_len += MAX (256, v_uint);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* handle invalid cases
|
||||||
|
*/
|
||||||
|
case '\000':
|
||||||
|
/* no conversion specification, bad bad */
|
||||||
|
conv_len += format - spec_start;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* ignore unknow/invalid flags */
|
g_warning (G_GNUC_PRETTY_FUNCTION
|
||||||
|
"(): unable to handle `%c' while parsing format",
|
||||||
|
c);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
conv_done |= conv_len > 0;
|
||||||
}
|
}
|
||||||
}
|
while (!conv_done);
|
||||||
else
|
/* handle width specifications */
|
||||||
len += 1;
|
conv_len = MAX (conv_len, MAX (spec.precision, spec.min_width));
|
||||||
}
|
/* handle flags */
|
||||||
|
conv_len += spec.alternate_format ? 2 : 0;
|
||||||
|
conv_len += (spec.add_space || spec.add_sign || spec.possible_sign);
|
||||||
|
/* finally done */
|
||||||
|
len += conv_len;
|
||||||
|
} /* else (c == '%') */
|
||||||
|
} /* while (*format) */
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
4
gmain.c
4
gmain.c
@ -1362,7 +1362,7 @@ g_idle_dispatch (gpointer source_data,
|
|||||||
GTimeVal *dispatch_time,
|
GTimeVal *dispatch_time,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GSourceFunc func = source_data;
|
GSourceFunc func = (GSourceFunc) source_data;
|
||||||
|
|
||||||
return func (user_data);
|
return func (user_data);
|
||||||
}
|
}
|
||||||
@ -1375,7 +1375,7 @@ g_idle_add_full (gint priority,
|
|||||||
{
|
{
|
||||||
g_return_val_if_fail (function != NULL, 0);
|
g_return_val_if_fail (function != NULL, 0);
|
||||||
|
|
||||||
return g_source_add (priority, FALSE, &idle_funcs, function, data, notify);
|
return g_source_add (priority, FALSE, &idle_funcs, (gpointer) function, data, notify);
|
||||||
}
|
}
|
||||||
|
|
||||||
guint
|
guint
|
||||||
|
359
gstrfuncs.c
359
gstrfuncs.c
@ -37,6 +37,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <ctype.h> /* For tolower() */
|
#include <ctype.h> /* For tolower() */
|
||||||
#if !defined (HAVE_STRSIGNAL) || !defined(NO_SYS_SIGLIST_DECL)
|
#if !defined (HAVE_STRSIGNAL) || !defined(NO_SYS_SIGLIST_DECL)
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@ -46,6 +47,36 @@
|
|||||||
* inteferes with g_strsignal() on some OSes
|
* inteferes with g_strsignal() on some OSes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
typedef union _GDoubleIEEE754 GDoubleIEEE754;
|
||||||
|
#define G_IEEE754_DOUBLE_BIAS (1023)
|
||||||
|
/* multiply with base2 exponent to get base10 exponent (nomal numbers) */
|
||||||
|
#define G_LOG_2_BASE_10 (0.30102999566398119521)
|
||||||
|
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||||
|
union _GDoubleIEEE754
|
||||||
|
{
|
||||||
|
gdouble v_double;
|
||||||
|
struct {
|
||||||
|
guint mantissa_low : 32;
|
||||||
|
guint mantissa_high : 20;
|
||||||
|
guint biased_exponent : 11;
|
||||||
|
guint sign : 1;
|
||||||
|
} mpn;
|
||||||
|
};
|
||||||
|
#elif G_BYTE_ORDER == G_BIG_ENDIAN
|
||||||
|
union _GDoubleIEEE754
|
||||||
|
{
|
||||||
|
gdouble v_double;
|
||||||
|
struct {
|
||||||
|
guint sign : 1;
|
||||||
|
guint biased_exponent : 11;
|
||||||
|
guint mantissa_high : 20;
|
||||||
|
guint mantissa_low : 32;
|
||||||
|
} mpn;
|
||||||
|
};
|
||||||
|
#else /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
|
||||||
|
#error unknown ENDIAN type
|
||||||
|
#endif /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
|
||||||
|
|
||||||
gchar*
|
gchar*
|
||||||
g_strdup (const gchar *str)
|
g_strdup (const gchar *str)
|
||||||
{
|
{
|
||||||
@ -791,32 +822,81 @@ g_strsignal (gint signum)
|
|||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
guint min_width;
|
||||||
|
guint precision;
|
||||||
|
gboolean alternate_format, zero_padding, adjust_left, locale_grouping;
|
||||||
|
gboolean add_space, add_sign, possible_sign, seen_precision;
|
||||||
|
gboolean mod_half, mod_long, mod_extra_long;
|
||||||
|
} PrintfArgSpec;
|
||||||
|
|
||||||
guint
|
guint
|
||||||
g_printf_string_upper_bound (const gchar* format,
|
g_printf_string_upper_bound (const gchar* format,
|
||||||
va_list args)
|
va_list args)
|
||||||
{
|
{
|
||||||
|
static const gboolean honour_longs = SIZEOF_LONG > 4 || SIZEOF_VOID_P > 4;
|
||||||
guint len = 1;
|
guint len = 1;
|
||||||
|
|
||||||
|
if (!format)
|
||||||
|
return len;
|
||||||
|
|
||||||
while (*format)
|
while (*format)
|
||||||
{
|
{
|
||||||
gboolean long_int = FALSE;
|
register gchar c = *format++;
|
||||||
gboolean extra_long = FALSE;
|
|
||||||
gchar c;
|
|
||||||
|
|
||||||
|
if (c != '%')
|
||||||
|
len += 1;
|
||||||
|
else /* (c == '%') */
|
||||||
|
{
|
||||||
|
PrintfArgSpec spec = { 0, };
|
||||||
|
gboolean seen_l = FALSE, conv_done = FALSE;
|
||||||
|
guint conv_len = 0;
|
||||||
|
const gchar *spec_start = format;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
c = *format++;
|
c = *format++;
|
||||||
|
switch (c)
|
||||||
if (c == '%')
|
|
||||||
{
|
{
|
||||||
gboolean done = FALSE;
|
GDoubleIEEE754 u_double;
|
||||||
|
guint v_uint;
|
||||||
|
gint v_int;
|
||||||
|
const gchar *v_string;
|
||||||
|
|
||||||
while (*format && !done)
|
/* beware of positional parameters
|
||||||
{
|
*/
|
||||||
switch (*format++)
|
case '$':
|
||||||
{
|
g_warning (G_GNUC_PRETTY_FUNCTION
|
||||||
gchar *string_arg;
|
"(): unable to handle positional parameters (%%n$)");
|
||||||
|
len += 1024; /* try adding some safety padding */
|
||||||
|
break;
|
||||||
|
|
||||||
case '*':
|
/* parse flags
|
||||||
len += va_arg (args, int);
|
*/
|
||||||
|
case '#':
|
||||||
|
spec.alternate_format = TRUE;
|
||||||
|
break;
|
||||||
|
case '0':
|
||||||
|
spec.zero_padding = TRUE;
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
spec.adjust_left = TRUE;
|
||||||
|
break;
|
||||||
|
case ' ':
|
||||||
|
spec.add_space = TRUE;
|
||||||
|
break;
|
||||||
|
case '+':
|
||||||
|
spec.add_sign = TRUE;
|
||||||
|
break;
|
||||||
|
case '\'':
|
||||||
|
spec.locale_grouping = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* parse output size specifications
|
||||||
|
*/
|
||||||
|
case '.':
|
||||||
|
spec.seen_precision = TRUE;
|
||||||
break;
|
break;
|
||||||
case '1':
|
case '1':
|
||||||
case '2':
|
case '2':
|
||||||
@ -827,107 +907,224 @@ g_printf_string_upper_bound (const gchar* format,
|
|||||||
case '7':
|
case '7':
|
||||||
case '8':
|
case '8':
|
||||||
case '9':
|
case '9':
|
||||||
/* add specified format length, since it might exceed the
|
v_uint = c - '0';
|
||||||
* size we assume it to have.
|
c = *format;
|
||||||
*/
|
while (c >= '0' && c <= '9')
|
||||||
format -= 1;
|
{
|
||||||
len += strtol (format, (char**) &format, 10);
|
format++;
|
||||||
|
v_uint = v_uint * 10 + c - '0';
|
||||||
|
c = *format;
|
||||||
|
}
|
||||||
|
if (spec.seen_precision)
|
||||||
|
spec.precision = MAX (spec.precision, v_uint);
|
||||||
|
else
|
||||||
|
spec.min_width = MAX (spec.min_width, v_uint);
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case '*':
|
||||||
/* ignore short int flag, since all args have at least the
|
v_int = va_arg (args, int);
|
||||||
* same size as an int
|
if (spec.seen_precision)
|
||||||
|
{
|
||||||
|
/* forget about negative precision */
|
||||||
|
if (v_int >= 0)
|
||||||
|
spec.precision = MAX (spec.precision, v_int);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (v_int < 0)
|
||||||
|
{
|
||||||
|
v_int = - v_int;
|
||||||
|
spec.adjust_left = TRUE;
|
||||||
|
}
|
||||||
|
spec.min_width = MAX (spec.min_width, v_int);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* parse type modifiers
|
||||||
*/
|
*/
|
||||||
|
case 'h':
|
||||||
|
spec.mod_half = TRUE;
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
if (long_int)
|
if (!seen_l)
|
||||||
extra_long = TRUE; /* linux specific */
|
|
||||||
else
|
|
||||||
long_int = TRUE;
|
|
||||||
break;
|
|
||||||
case 'q':
|
|
||||||
case 'L':
|
|
||||||
long_int = TRUE;
|
|
||||||
extra_long = TRUE;
|
|
||||||
break;
|
|
||||||
case '\'':
|
|
||||||
len += 64;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
string_arg = va_arg (args, char *);
|
|
||||||
if (string_arg)
|
|
||||||
len += strlen (string_arg);
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* add enough padding to hold "(null)" identifier */
|
spec.mod_long = TRUE;
|
||||||
len += 16;
|
seen_l = TRUE;
|
||||||
}
|
|
||||||
done = TRUE;
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
/* else, fall through */
|
||||||
|
case 'L':
|
||||||
|
case 'q':
|
||||||
|
spec.mod_long = TRUE;
|
||||||
|
spec.mod_extra_long = TRUE;
|
||||||
|
break;
|
||||||
|
case 'z':
|
||||||
|
case 'Z':
|
||||||
|
#if GLIB_SIZEOF_SIZE_T > 4
|
||||||
|
spec.mod_long = TRUE;
|
||||||
|
spec.mod_extra_long = TRUE;
|
||||||
|
#endif /* GLIB_SIZEOF_SIZE_T > 4 */
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
#if GLIB_SIZEOF_PTRDIFF_T > 4
|
||||||
|
spec.mod_long = TRUE;
|
||||||
|
spec.mod_extra_long = TRUE;
|
||||||
|
#endif /* GLIB_SIZEOF_PTRDIFF_T > 4 */
|
||||||
|
break;
|
||||||
|
case 'j':
|
||||||
|
#if GLIB_SIZEOF_INTMAX_T > 4
|
||||||
|
spec.mod_long = TRUE;
|
||||||
|
spec.mod_extra_long = TRUE;
|
||||||
|
#endif /* GLIB_SIZEOF_INTMAX_T > 4 */
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* parse output conversions
|
||||||
|
*/
|
||||||
|
case '%':
|
||||||
|
conv_len += 1;
|
||||||
|
break;
|
||||||
|
case 'O':
|
||||||
|
case 'D':
|
||||||
|
case 'I':
|
||||||
|
case 'U':
|
||||||
|
/* some C libraries feature long variants for these as well? */
|
||||||
|
spec.mod_long = TRUE;
|
||||||
|
/* fall through */
|
||||||
|
case 'o':
|
||||||
|
conv_len += 2;
|
||||||
|
/* fall through */
|
||||||
case 'd':
|
case 'd':
|
||||||
case 'i':
|
case 'i':
|
||||||
case 'o':
|
conv_len += 1; /* sign */
|
||||||
|
/* fall through */
|
||||||
case 'u':
|
case 'u':
|
||||||
|
conv_len += 4;
|
||||||
|
/* fall through */
|
||||||
case 'x':
|
case 'x':
|
||||||
case 'X':
|
case 'X':
|
||||||
#ifdef G_HAVE_GINT64
|
spec.possible_sign = TRUE;
|
||||||
if (extra_long)
|
conv_len += 10;
|
||||||
(void) va_arg (args, gint64);
|
if (spec.mod_long && honour_longs)
|
||||||
else
|
conv_len *= 2;
|
||||||
#endif /* G_HAVE_GINT64 */
|
if (spec.mod_extra_long)
|
||||||
|
conv_len *= 2;
|
||||||
|
if (spec.mod_extra_long)
|
||||||
{
|
{
|
||||||
if (long_int)
|
#ifdef G_HAVE_GINT64
|
||||||
|
(void) va_arg (args, gint64);
|
||||||
|
#else /* !G_HAVE_GINT64 */
|
||||||
|
(void) va_arg (args, long);
|
||||||
|
#endif /* !G_HAVE_GINT64 */
|
||||||
|
}
|
||||||
|
else if (spec.mod_long)
|
||||||
(void) va_arg (args, long);
|
(void) va_arg (args, long);
|
||||||
else
|
else
|
||||||
(void) va_arg (args, int);
|
(void) va_arg (args, int);
|
||||||
}
|
|
||||||
len += extra_long ? 64 : 32;
|
|
||||||
done = TRUE;
|
|
||||||
break;
|
|
||||||
case 'D':
|
|
||||||
case 'O':
|
|
||||||
case 'U':
|
|
||||||
(void) va_arg (args, long);
|
|
||||||
len += 32;
|
|
||||||
done = TRUE;
|
|
||||||
break;
|
break;
|
||||||
|
case 'A':
|
||||||
|
case 'a':
|
||||||
|
/* 0x */
|
||||||
|
conv_len += 2;
|
||||||
|
/* fall through */
|
||||||
|
case 'g':
|
||||||
|
case 'G':
|
||||||
case 'e':
|
case 'e':
|
||||||
case 'E':
|
case 'E':
|
||||||
case 'f':
|
case 'f':
|
||||||
case 'g':
|
spec.possible_sign = TRUE;
|
||||||
case 'G':
|
/* n . dddddddddddddddddddddddd E +- eeee */
|
||||||
|
conv_len += 1 + 1 + MAX (24, spec.precision) + 1 + 1 + 4;
|
||||||
|
if (spec.mod_extra_long)
|
||||||
|
g_warning (G_GNUC_PRETTY_FUNCTION
|
||||||
|
"(): unable to handle long double, collecting double only");
|
||||||
#ifdef HAVE_LONG_DOUBLE
|
#ifdef HAVE_LONG_DOUBLE
|
||||||
if (extra_long)
|
#error need to implement special handling for long double
|
||||||
(void) va_arg (args, long double);
|
#endif
|
||||||
else
|
u_double.v_double = va_arg (args, double);
|
||||||
#endif /* HAVE_LONG_DOUBLE */
|
/* %f can expand up to all significant digits before '.' (308) */
|
||||||
(void) va_arg (args, double);
|
if (c == 'f' &&
|
||||||
len += extra_long ? 128 : 64;
|
u_double.mpn.biased_exponent > 0 && u_double.mpn.biased_exponent < 2047)
|
||||||
done = TRUE;
|
{
|
||||||
|
gint exp = u_double.mpn.biased_exponent;
|
||||||
|
|
||||||
|
exp -= G_IEEE754_DOUBLE_BIAS;
|
||||||
|
exp = exp * G_LOG_2_BASE_10 + 1;
|
||||||
|
conv_len += exp;
|
||||||
|
}
|
||||||
|
/* some printf() implementations require extra padding for rounding */
|
||||||
|
conv_len += 2;
|
||||||
|
/* we can't really handle locale specific grouping here */
|
||||||
|
if (spec.locale_grouping)
|
||||||
|
conv_len *= 2;
|
||||||
break;
|
break;
|
||||||
|
case 'C':
|
||||||
|
spec.mod_long = TRUE;
|
||||||
|
/* fall through */
|
||||||
case 'c':
|
case 'c':
|
||||||
|
conv_len += spec.mod_long ? MB_LEN_MAX : 1;
|
||||||
(void) va_arg (args, int);
|
(void) va_arg (args, int);
|
||||||
len += 1;
|
|
||||||
done = TRUE;
|
|
||||||
break;
|
break;
|
||||||
|
case 'S':
|
||||||
|
spec.mod_long = TRUE;
|
||||||
|
/* fall through */
|
||||||
|
case 's':
|
||||||
|
v_string = va_arg (args, char*);
|
||||||
|
if (!v_string)
|
||||||
|
conv_len += 8; /* hold "(null)" */
|
||||||
|
else if (spec.seen_precision)
|
||||||
|
conv_len += spec.precision;
|
||||||
|
else
|
||||||
|
conv_len += strlen (v_string);
|
||||||
|
conv_done = TRUE;
|
||||||
|
if (spec.mod_long)
|
||||||
|
{
|
||||||
|
g_warning (G_GNUC_PRETTY_FUNCTION
|
||||||
|
"(): unable to handle wide char strings");
|
||||||
|
len += 1024; /* try adding some safety padding */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'P': /* do we actually need this? */
|
||||||
|
/* fall through */
|
||||||
case 'p':
|
case 'p':
|
||||||
|
spec.alternate_format = TRUE;
|
||||||
|
conv_len += 10;
|
||||||
|
if (honour_longs)
|
||||||
|
conv_len *= 2;
|
||||||
|
/* fall through */
|
||||||
case 'n':
|
case 'n':
|
||||||
|
conv_done = TRUE;
|
||||||
(void) va_arg (args, void*);
|
(void) va_arg (args, void*);
|
||||||
len += 32;
|
|
||||||
done = TRUE;
|
|
||||||
break;
|
break;
|
||||||
case '%':
|
case 'm':
|
||||||
len += 1;
|
/* there's not much we can do to be clever */
|
||||||
done = TRUE;
|
v_string = g_strerror (errno);
|
||||||
|
v_uint = v_string ? strlen (v_string) : 0;
|
||||||
|
conv_len += MAX (256, v_uint);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* handle invalid cases
|
||||||
|
*/
|
||||||
|
case '\000':
|
||||||
|
/* no conversion specification, bad bad */
|
||||||
|
conv_len += format - spec_start;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* ignore unknow/invalid flags */
|
g_warning (G_GNUC_PRETTY_FUNCTION
|
||||||
|
"(): unable to handle `%c' while parsing format",
|
||||||
|
c);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
conv_done |= conv_len > 0;
|
||||||
}
|
}
|
||||||
}
|
while (!conv_done);
|
||||||
else
|
/* handle width specifications */
|
||||||
len += 1;
|
conv_len = MAX (conv_len, MAX (spec.precision, spec.min_width));
|
||||||
}
|
/* handle flags */
|
||||||
|
conv_len += spec.alternate_format ? 2 : 0;
|
||||||
|
conv_len += (spec.add_space || spec.add_sign || spec.possible_sign);
|
||||||
|
/* finally done */
|
||||||
|
len += conv_len;
|
||||||
|
} /* else (c == '%') */
|
||||||
|
} /* while (*format) */
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user