From 30a1e1addb131e3e200f91e9f93e3fc0709f3809 Mon Sep 17 00:00:00 2001 From: Tim Janik Date: Tue, 12 Oct 1999 12:08:13 +0000 Subject: [PATCH] completly new implementation for printf string upper bounds calculation. Tue Oct 12 12:16:12 1999 Tim Janik * gmessages.c (g_printf_string_upper_bound): completly new implementation for printf string upper bounds calculation. we handle all glibc 2.1 format specifiers now, except for positional parameters (%nn$...) and wide char strings, plus some obscure upper case variants of the standard conversions. this fixes a lot of bugs in the old code, i.e. - NULL format strings - floats with exponents >+24 - %G - precision specifications in general - negative field widths - %p for SIZEOF_VOID_P > 4 platforms we now issue warnigns in places where the old code would have caused buffer overruns anyways. warnings are suppressed when invoked from glogv(), to avoid infinite recursions if someone passes a log message that comes with really obscure format specifications. Tue Oct 12 11:49:00 1999 Tim Janik * gstrfuncs.c: nuked old g_printf_string_upper_bound() version. Tue Oct 12 03:34:40 1999 Tim Janik * glib.h: added GFloatIEEE754 and GDoubleIEEE754 unions to access sign, mantissa and exponent of IEEE floats and doubles (required by the new version of g_printf_string_upper_bound). the unions are endian specific, we handle G_LITTLE_ENDIAN and G_BIG_ENDIAN as of currently. ieee floats and doubles are supported (used for storage) by at least intel, ppc and sparc, reference: http://twister.ou.edu/workshop.docs/common-tools/numerical_comp_guide/ncg_math.doc.html Mon Oct 11 18:01:49 1999 Tim Janik * configure.in: added additional checks to figure sizes of size_t, ptrdiff_t and intmax_t (required by g_printf_string_upper_bound). --- ChangeLog | 38 +++++ ChangeLog.pre-2-0 | 38 +++++ ChangeLog.pre-2-10 | 38 +++++ ChangeLog.pre-2-12 | 38 +++++ ChangeLog.pre-2-2 | 38 +++++ ChangeLog.pre-2-4 | 38 +++++ ChangeLog.pre-2-6 | 38 +++++ ChangeLog.pre-2-8 | 38 +++++ acconfig.h | 4 + configure.in | 27 +++- glib.h | 68 +++++++++ glib/glib.h | 68 +++++++++ glib/gmessages.c | 413 +++++++++++++++++++++++++++++++++++++++++++++++------ glib/gstrfuncs.c | 137 ------------------ gmessages.c | 413 +++++++++++++++++++++++++++++++++++++++++++++++------ gstrfuncs.c | 137 ------------------ 16 files changed, 1209 insertions(+), 362 deletions(-) diff --git a/ChangeLog b/ChangeLog index dc7807b..fb9c4a5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,41 @@ +Tue Oct 12 12:16:12 1999 Tim Janik + + * gmessages.c (g_printf_string_upper_bound): completly new implementation + for printf string upper bounds calculation. + we handle all glibc 2.1 format specifiers now, except for positional + parameters (%nn$...) and wide char strings, plus some obscure upper + case variants of the standard conversions. this fixes a lot of + bugs in the old code, i.e. + - NULL format strings + - floats with exponents >+24 + - %G + - precision specifications in general + - negative field widths + - %p for SIZEOF_VOID_P > 4 platforms + we now issue warnigns in places where the old code would have + caused buffer overruns anyways. warnings are suppressed when invoked + from glogv(), to avoid infinite recursions if someone passes a log + message that comes with really obscure format specifications. + +Tue Oct 12 11:49:00 1999 Tim Janik + + * gstrfuncs.c: nuked old g_printf_string_upper_bound() version. + +Tue Oct 12 03:34:40 1999 Tim Janik + + * glib.h: added GFloatIEEE754 and GDoubleIEEE754 unions to access sign, + mantissa and exponent of IEEE floats and doubles (required by the new + version of g_printf_string_upper_bound). the unions are endian specific, + we handle G_LITTLE_ENDIAN and G_BIG_ENDIAN as of currently. ieee floats + and doubles are supported (used for storage) by at least intel, ppc and + sparc, reference: + http://twister.ou.edu/workshop.docs/common-tools/numerical_comp_guide/ncg_math.doc.html + +Mon Oct 11 18:01:49 1999 Tim Janik + + * configure.in: added additional checks to figure sizes of size_t, + ptrdiff_t and intmax_t (required by g_printf_string_upper_bound). + Wed Oct 6 12:44:23 PDT 1999 Manish Singh * configure.in: blah. use G_WITH_CYGWIN instead of G_HAVE_CYGWIN diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index dc7807b..fb9c4a5 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,41 @@ +Tue Oct 12 12:16:12 1999 Tim Janik + + * gmessages.c (g_printf_string_upper_bound): completly new implementation + for printf string upper bounds calculation. + we handle all glibc 2.1 format specifiers now, except for positional + parameters (%nn$...) and wide char strings, plus some obscure upper + case variants of the standard conversions. this fixes a lot of + bugs in the old code, i.e. + - NULL format strings + - floats with exponents >+24 + - %G + - precision specifications in general + - negative field widths + - %p for SIZEOF_VOID_P > 4 platforms + we now issue warnigns in places where the old code would have + caused buffer overruns anyways. warnings are suppressed when invoked + from glogv(), to avoid infinite recursions if someone passes a log + message that comes with really obscure format specifications. + +Tue Oct 12 11:49:00 1999 Tim Janik + + * gstrfuncs.c: nuked old g_printf_string_upper_bound() version. + +Tue Oct 12 03:34:40 1999 Tim Janik + + * glib.h: added GFloatIEEE754 and GDoubleIEEE754 unions to access sign, + mantissa and exponent of IEEE floats and doubles (required by the new + version of g_printf_string_upper_bound). the unions are endian specific, + we handle G_LITTLE_ENDIAN and G_BIG_ENDIAN as of currently. ieee floats + and doubles are supported (used for storage) by at least intel, ppc and + sparc, reference: + http://twister.ou.edu/workshop.docs/common-tools/numerical_comp_guide/ncg_math.doc.html + +Mon Oct 11 18:01:49 1999 Tim Janik + + * configure.in: added additional checks to figure sizes of size_t, + ptrdiff_t and intmax_t (required by g_printf_string_upper_bound). + Wed Oct 6 12:44:23 PDT 1999 Manish Singh * configure.in: blah. use G_WITH_CYGWIN instead of G_HAVE_CYGWIN diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index dc7807b..fb9c4a5 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,41 @@ +Tue Oct 12 12:16:12 1999 Tim Janik + + * gmessages.c (g_printf_string_upper_bound): completly new implementation + for printf string upper bounds calculation. + we handle all glibc 2.1 format specifiers now, except for positional + parameters (%nn$...) and wide char strings, plus some obscure upper + case variants of the standard conversions. this fixes a lot of + bugs in the old code, i.e. + - NULL format strings + - floats with exponents >+24 + - %G + - precision specifications in general + - negative field widths + - %p for SIZEOF_VOID_P > 4 platforms + we now issue warnigns in places where the old code would have + caused buffer overruns anyways. warnings are suppressed when invoked + from glogv(), to avoid infinite recursions if someone passes a log + message that comes with really obscure format specifications. + +Tue Oct 12 11:49:00 1999 Tim Janik + + * gstrfuncs.c: nuked old g_printf_string_upper_bound() version. + +Tue Oct 12 03:34:40 1999 Tim Janik + + * glib.h: added GFloatIEEE754 and GDoubleIEEE754 unions to access sign, + mantissa and exponent of IEEE floats and doubles (required by the new + version of g_printf_string_upper_bound). the unions are endian specific, + we handle G_LITTLE_ENDIAN and G_BIG_ENDIAN as of currently. ieee floats + and doubles are supported (used for storage) by at least intel, ppc and + sparc, reference: + http://twister.ou.edu/workshop.docs/common-tools/numerical_comp_guide/ncg_math.doc.html + +Mon Oct 11 18:01:49 1999 Tim Janik + + * configure.in: added additional checks to figure sizes of size_t, + ptrdiff_t and intmax_t (required by g_printf_string_upper_bound). + Wed Oct 6 12:44:23 PDT 1999 Manish Singh * configure.in: blah. use G_WITH_CYGWIN instead of G_HAVE_CYGWIN diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12 index dc7807b..fb9c4a5 100644 --- a/ChangeLog.pre-2-12 +++ b/ChangeLog.pre-2-12 @@ -1,3 +1,41 @@ +Tue Oct 12 12:16:12 1999 Tim Janik + + * gmessages.c (g_printf_string_upper_bound): completly new implementation + for printf string upper bounds calculation. + we handle all glibc 2.1 format specifiers now, except for positional + parameters (%nn$...) and wide char strings, plus some obscure upper + case variants of the standard conversions. this fixes a lot of + bugs in the old code, i.e. + - NULL format strings + - floats with exponents >+24 + - %G + - precision specifications in general + - negative field widths + - %p for SIZEOF_VOID_P > 4 platforms + we now issue warnigns in places where the old code would have + caused buffer overruns anyways. warnings are suppressed when invoked + from glogv(), to avoid infinite recursions if someone passes a log + message that comes with really obscure format specifications. + +Tue Oct 12 11:49:00 1999 Tim Janik + + * gstrfuncs.c: nuked old g_printf_string_upper_bound() version. + +Tue Oct 12 03:34:40 1999 Tim Janik + + * glib.h: added GFloatIEEE754 and GDoubleIEEE754 unions to access sign, + mantissa and exponent of IEEE floats and doubles (required by the new + version of g_printf_string_upper_bound). the unions are endian specific, + we handle G_LITTLE_ENDIAN and G_BIG_ENDIAN as of currently. ieee floats + and doubles are supported (used for storage) by at least intel, ppc and + sparc, reference: + http://twister.ou.edu/workshop.docs/common-tools/numerical_comp_guide/ncg_math.doc.html + +Mon Oct 11 18:01:49 1999 Tim Janik + + * configure.in: added additional checks to figure sizes of size_t, + ptrdiff_t and intmax_t (required by g_printf_string_upper_bound). + Wed Oct 6 12:44:23 PDT 1999 Manish Singh * configure.in: blah. use G_WITH_CYGWIN instead of G_HAVE_CYGWIN diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index dc7807b..fb9c4a5 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,41 @@ +Tue Oct 12 12:16:12 1999 Tim Janik + + * gmessages.c (g_printf_string_upper_bound): completly new implementation + for printf string upper bounds calculation. + we handle all glibc 2.1 format specifiers now, except for positional + parameters (%nn$...) and wide char strings, plus some obscure upper + case variants of the standard conversions. this fixes a lot of + bugs in the old code, i.e. + - NULL format strings + - floats with exponents >+24 + - %G + - precision specifications in general + - negative field widths + - %p for SIZEOF_VOID_P > 4 platforms + we now issue warnigns in places where the old code would have + caused buffer overruns anyways. warnings are suppressed when invoked + from glogv(), to avoid infinite recursions if someone passes a log + message that comes with really obscure format specifications. + +Tue Oct 12 11:49:00 1999 Tim Janik + + * gstrfuncs.c: nuked old g_printf_string_upper_bound() version. + +Tue Oct 12 03:34:40 1999 Tim Janik + + * glib.h: added GFloatIEEE754 and GDoubleIEEE754 unions to access sign, + mantissa and exponent of IEEE floats and doubles (required by the new + version of g_printf_string_upper_bound). the unions are endian specific, + we handle G_LITTLE_ENDIAN and G_BIG_ENDIAN as of currently. ieee floats + and doubles are supported (used for storage) by at least intel, ppc and + sparc, reference: + http://twister.ou.edu/workshop.docs/common-tools/numerical_comp_guide/ncg_math.doc.html + +Mon Oct 11 18:01:49 1999 Tim Janik + + * configure.in: added additional checks to figure sizes of size_t, + ptrdiff_t and intmax_t (required by g_printf_string_upper_bound). + Wed Oct 6 12:44:23 PDT 1999 Manish Singh * configure.in: blah. use G_WITH_CYGWIN instead of G_HAVE_CYGWIN diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index dc7807b..fb9c4a5 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,41 @@ +Tue Oct 12 12:16:12 1999 Tim Janik + + * gmessages.c (g_printf_string_upper_bound): completly new implementation + for printf string upper bounds calculation. + we handle all glibc 2.1 format specifiers now, except for positional + parameters (%nn$...) and wide char strings, plus some obscure upper + case variants of the standard conversions. this fixes a lot of + bugs in the old code, i.e. + - NULL format strings + - floats with exponents >+24 + - %G + - precision specifications in general + - negative field widths + - %p for SIZEOF_VOID_P > 4 platforms + we now issue warnigns in places where the old code would have + caused buffer overruns anyways. warnings are suppressed when invoked + from glogv(), to avoid infinite recursions if someone passes a log + message that comes with really obscure format specifications. + +Tue Oct 12 11:49:00 1999 Tim Janik + + * gstrfuncs.c: nuked old g_printf_string_upper_bound() version. + +Tue Oct 12 03:34:40 1999 Tim Janik + + * glib.h: added GFloatIEEE754 and GDoubleIEEE754 unions to access sign, + mantissa and exponent of IEEE floats and doubles (required by the new + version of g_printf_string_upper_bound). the unions are endian specific, + we handle G_LITTLE_ENDIAN and G_BIG_ENDIAN as of currently. ieee floats + and doubles are supported (used for storage) by at least intel, ppc and + sparc, reference: + http://twister.ou.edu/workshop.docs/common-tools/numerical_comp_guide/ncg_math.doc.html + +Mon Oct 11 18:01:49 1999 Tim Janik + + * configure.in: added additional checks to figure sizes of size_t, + ptrdiff_t and intmax_t (required by g_printf_string_upper_bound). + Wed Oct 6 12:44:23 PDT 1999 Manish Singh * configure.in: blah. use G_WITH_CYGWIN instead of G_HAVE_CYGWIN diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index dc7807b..fb9c4a5 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,41 @@ +Tue Oct 12 12:16:12 1999 Tim Janik + + * gmessages.c (g_printf_string_upper_bound): completly new implementation + for printf string upper bounds calculation. + we handle all glibc 2.1 format specifiers now, except for positional + parameters (%nn$...) and wide char strings, plus some obscure upper + case variants of the standard conversions. this fixes a lot of + bugs in the old code, i.e. + - NULL format strings + - floats with exponents >+24 + - %G + - precision specifications in general + - negative field widths + - %p for SIZEOF_VOID_P > 4 platforms + we now issue warnigns in places where the old code would have + caused buffer overruns anyways. warnings are suppressed when invoked + from glogv(), to avoid infinite recursions if someone passes a log + message that comes with really obscure format specifications. + +Tue Oct 12 11:49:00 1999 Tim Janik + + * gstrfuncs.c: nuked old g_printf_string_upper_bound() version. + +Tue Oct 12 03:34:40 1999 Tim Janik + + * glib.h: added GFloatIEEE754 and GDoubleIEEE754 unions to access sign, + mantissa and exponent of IEEE floats and doubles (required by the new + version of g_printf_string_upper_bound). the unions are endian specific, + we handle G_LITTLE_ENDIAN and G_BIG_ENDIAN as of currently. ieee floats + and doubles are supported (used for storage) by at least intel, ppc and + sparc, reference: + http://twister.ou.edu/workshop.docs/common-tools/numerical_comp_guide/ncg_math.doc.html + +Mon Oct 11 18:01:49 1999 Tim Janik + + * configure.in: added additional checks to figure sizes of size_t, + ptrdiff_t and intmax_t (required by g_printf_string_upper_bound). + Wed Oct 6 12:44:23 PDT 1999 Manish Singh * configure.in: blah. use G_WITH_CYGWIN instead of G_HAVE_CYGWIN diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index dc7807b..fb9c4a5 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,41 @@ +Tue Oct 12 12:16:12 1999 Tim Janik + + * gmessages.c (g_printf_string_upper_bound): completly new implementation + for printf string upper bounds calculation. + we handle all glibc 2.1 format specifiers now, except for positional + parameters (%nn$...) and wide char strings, plus some obscure upper + case variants of the standard conversions. this fixes a lot of + bugs in the old code, i.e. + - NULL format strings + - floats with exponents >+24 + - %G + - precision specifications in general + - negative field widths + - %p for SIZEOF_VOID_P > 4 platforms + we now issue warnigns in places where the old code would have + caused buffer overruns anyways. warnings are suppressed when invoked + from glogv(), to avoid infinite recursions if someone passes a log + message that comes with really obscure format specifications. + +Tue Oct 12 11:49:00 1999 Tim Janik + + * gstrfuncs.c: nuked old g_printf_string_upper_bound() version. + +Tue Oct 12 03:34:40 1999 Tim Janik + + * glib.h: added GFloatIEEE754 and GDoubleIEEE754 unions to access sign, + mantissa and exponent of IEEE floats and doubles (required by the new + version of g_printf_string_upper_bound). the unions are endian specific, + we handle G_LITTLE_ENDIAN and G_BIG_ENDIAN as of currently. ieee floats + and doubles are supported (used for storage) by at least intel, ppc and + sparc, reference: + http://twister.ou.edu/workshop.docs/common-tools/numerical_comp_guide/ncg_math.doc.html + +Mon Oct 11 18:01:49 1999 Tim Janik + + * configure.in: added additional checks to figure sizes of size_t, + ptrdiff_t and intmax_t (required by g_printf_string_upper_bound). + Wed Oct 6 12:44:23 PDT 1999 Manish Singh * configure.in: blah. use G_WITH_CYGWIN instead of G_HAVE_CYGWIN diff --git a/acconfig.h b/acconfig.h index f0b6937..c716783 100644 --- a/acconfig.h +++ b/acconfig.h @@ -44,7 +44,11 @@ #undef G_THREADS_ENABLED #undef GLIB_SIZEOF_GMUTEX +#undef GLIB_SIZEOF_INTMAX_T #undef GLIB_SIZEOF_PTHREAD_T +#undef GLIB_SIZEOF_PTRDIFF_T +#undef GLIB_SIZEOF_SIZE_T + #undef GLIB_BYTE_CONTENTS_GMUTEX #undef GLIB_BYTE_CONTENTS_GRECMUTEX diff --git a/configure.in b/configure.in index 3426578..7b7a77b 100644 --- a/configure.in +++ b/configure.in @@ -292,10 +292,10 @@ case x$glib_cv_hasinline in xyes) AC_DEFINE(G_HAVE_INLINE) esac -dnl for bytesex stuff +# check for bytesex stuff AC_C_BIGENDIAN -dnl header file checks +# xhexk for header files AC_CHECK_HEADERS(float.h, AC_DEFINE(HAVE_FLOAT_H)) AC_CHECK_HEADERS(limits.h, AC_DEFINE(HAVE_LIMITS_H)) AC_CHECK_HEADERS(pwd.h, AC_DEFINE(HAVE_PWD_H)) @@ -306,6 +306,29 @@ AC_CHECK_HEADERS(sys/time.h, AC_DEFINE(HAVE_SYS_TIME_H)) AC_CHECK_HEADERS(sys/times.h, AC_DEFINE(HAVE_SYS_TIMES_H)) AC_CHECK_HEADERS(unistd.h, AC_DEFINE(HAVE_UNISTD_H)) AC_CHECK_HEADERS(values.h, AC_DEFINE(HAVE_VALUES_H)) +AC_CHECK_HEADERS(stdint.h, AC_DEFINE(HAVE_VALUES_H)) + +# check additional type sizes +size_includes=[" +#include +#include +#include +#include +#include +"] +if test "x$ac_cv_header_stdint_h" = "xyes"; then + size_includes=["$size_includes +#include +"] +fi +if test "x$ac_cv_header_unistd_h" = "xyes"; then + size_includes=["$size_includes +#include +"] +fi +GLIB_SIZEOF([$size_includes], size_t, size_t) +GLIB_SIZEOF([$size_includes], ptrdiff_t, ptrdiff_t) +GLIB_SIZEOF([$size_includes], intmax_t, intmax_t) # Check for some functions AC_CHECK_FUNCS(lstat strerror strsignal memmove vsnprintf strcasecmp strncasecmp poll) diff --git a/glib.h b/glib.h index 4300fd3..6467012 100644 --- a/glib.h +++ b/glib.h @@ -690,6 +690,8 @@ typedef struct _GCache GCache; typedef struct _GCompletion GCompletion; typedef struct _GData GData; typedef struct _GDebugKey GDebugKey; +typedef union _GDoubleIEEE754 GDoubleIEEE754; +typedef union _GFloatIEEE754 GFloatIEEE754; typedef struct _GHashTable GHashTable; typedef struct _GHook GHook; typedef struct _GHookList GHookList; @@ -870,6 +872,72 @@ struct _GTuples }; +/* IEEE Standard 754 Single Precision Storage Format (gfloat): + * + * 31 30 23 22 0 + * +--------+---------------+---------------+ + * | s 1bit | e[30:23] 8bit | f[22:0] 23bit | + * +--------+---------------+---------------+ + * B0------------------->B1------->B2-->B3--> + * + * IEEE Standard 754 Double Precision Storage Format (gdouble): + * + * 63 62 52 51 32 31 0 + * +--------+----------------+----------------+ +---------------+ + * | s 1bit | e[62:52] 11bit | f[51:32] 20bit | | f[31:0] 32bit | + * +--------+----------------+----------------+ +---------------+ + * B0--------------->B1---------->B2--->B3----> B4->B5->B6->B7-> + */ +/* subtract from biased_exponent to form base2 exponent (normal numbers) */ +#define G_IEEE754_FLOAT_BIAS (127) +#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 _GFloatIEEE754 +{ + gfloat v_float; + struct { + guint mantissa : 23; + guint biased_exponent : 8; + guint sign : 1; + } mpn; +}; +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 _GFloatIEEE754 +{ + gfloat v_float; + struct { + guint sign : 1; + guint biased_exponent : 8; + guint mantissa : 23; + } mpn; +}; +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 */ + + /* Doubly linked lists */ void g_list_push_allocator (GAllocator *allocator); diff --git a/glib/glib.h b/glib/glib.h index 4300fd3..6467012 100644 --- a/glib/glib.h +++ b/glib/glib.h @@ -690,6 +690,8 @@ typedef struct _GCache GCache; typedef struct _GCompletion GCompletion; typedef struct _GData GData; typedef struct _GDebugKey GDebugKey; +typedef union _GDoubleIEEE754 GDoubleIEEE754; +typedef union _GFloatIEEE754 GFloatIEEE754; typedef struct _GHashTable GHashTable; typedef struct _GHook GHook; typedef struct _GHookList GHookList; @@ -870,6 +872,72 @@ struct _GTuples }; +/* IEEE Standard 754 Single Precision Storage Format (gfloat): + * + * 31 30 23 22 0 + * +--------+---------------+---------------+ + * | s 1bit | e[30:23] 8bit | f[22:0] 23bit | + * +--------+---------------+---------------+ + * B0------------------->B1------->B2-->B3--> + * + * IEEE Standard 754 Double Precision Storage Format (gdouble): + * + * 63 62 52 51 32 31 0 + * +--------+----------------+----------------+ +---------------+ + * | s 1bit | e[62:52] 11bit | f[51:32] 20bit | | f[31:0] 32bit | + * +--------+----------------+----------------+ +---------------+ + * B0--------------->B1---------->B2--->B3----> B4->B5->B6->B7-> + */ +/* subtract from biased_exponent to form base2 exponent (normal numbers) */ +#define G_IEEE754_FLOAT_BIAS (127) +#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 _GFloatIEEE754 +{ + gfloat v_float; + struct { + guint mantissa : 23; + guint biased_exponent : 8; + guint sign : 1; + } mpn; +}; +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 _GFloatIEEE754 +{ + gfloat v_float; + struct { + guint sign : 1; + guint biased_exponent : 8; + guint mantissa : 23; + } mpn; +}; +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 */ + + /* Doubly linked lists */ void g_list_push_allocator (GAllocator *allocator); diff --git a/glib/gmessages.c b/glib/gmessages.c index 4179f73..5f60218 100644 --- a/glib/gmessages.c +++ b/glib/gmessages.c @@ -41,42 +41,9 @@ #include #endif #include +#include +#include -#ifdef G_OS_WIN32 -# define STRICT -# include -# include /* For _getpid() */ - -/* Just use stdio. If we're out of memory, we're hosed anyway. */ -#undef write - -static inline int -write (FILE *fd, - const char *buf, - int len) -{ - fwrite (buf, len, 1, fd); - - return len; -} - -static void -ensure_stdout_valid (void) -{ - HANDLE handle; - - handle = GetStdHandle (STD_OUTPUT_HANDLE); - - if (handle == INVALID_HANDLE_VALUE) - { - AllocConsole (); - freopen ("CONOUT$", "w", stdout); - } -} -#else -#define ensure_stdout_valid() /* Define as empty */ -#endif - /* --- structures --- */ typedef struct _GLogDomain GLogDomain; @@ -98,6 +65,12 @@ struct _GLogHandler }; +/* --- prototypes --- */ +static inline guint printf_string_upper_bound (const gchar *format, + gboolean may_warn, + va_list args); + + /* --- variables --- */ static GMutex* g_messages_lock = NULL; @@ -115,8 +88,40 @@ static GPrivate* g_log_depth = NULL; /* --- functions --- */ +#ifdef G_OS_WIN32 +# define STRICT +# include +# include /* For _getpid() */ +/* Just use stdio. If we're out of memory, we're hosed anyway. */ +#undef write +static inline int +write (FILE *fd, + const char *buf, + int len) +{ + fwrite (buf, len, 1, fd); + + return len; +} +static void +ensure_stdout_valid (void) +{ + HANDLE handle; + + handle = GetStdHandle (STD_OUTPUT_HANDLE); + + if (handle == INVALID_HANDLE_VALUE) + { + AllocConsole (); + freopen ("CONOUT$", "w", stdout); + } +} +#else +#define ensure_stdout_valid() /* Define as empty */ +#endif + static inline GLogDomain* -g_log_find_domain (const gchar *log_domain) +g_log_find_domain (const gchar *log_domain) { register GLogDomain *domain; @@ -286,8 +291,8 @@ g_log_set_handler (const gchar *log_domain, } void -g_log_remove_handler (const gchar *log_domain, - guint handler_id) +g_log_remove_handler (const gchar *log_domain, + guint handler_id) { register GLogDomain *domain; @@ -324,10 +329,10 @@ g_log_remove_handler (const gchar *log_domain, } void -g_logv (const gchar *log_domain, - GLogLevelFlags log_level, - const gchar *format, - va_list args1) +g_logv (const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *format, + va_list args1) { va_list args2; gchar buffer[1025]; @@ -341,7 +346,7 @@ g_logv (const gchar *log_domain, * recursively. */ G_VA_COPY (args2, args1); - if (g_printf_string_upper_bound (format, args1) < 1024) + if (printf_string_upper_bound (format, FALSE, args1) < 1024) vsprintf (buffer, format, args2); else { @@ -793,6 +798,328 @@ g_set_message_handler (GPrintFunc func) return old_message_func; } +#ifndef MB_LEN_MAX +# define MB_LEN_MAX 8 +#endif + +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; + +static inline guint +printf_string_upper_bound (const gchar *format, + gboolean may_warn, + va_list args) +{ + static const gboolean honour_longs = SIZEOF_LONG > 4 || SIZEOF_VOID_P > 4; + guint len = 1; + + if (!format) + return len; + + while (*format) + { + register gchar c = *format++; + + 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++; + switch (c) + { + GDoubleIEEE754 u_double; + guint v_uint; + gint v_int; + gchar *v_string; + + /* beware of positional parameters + */ + case '$': + if (may_warn) + g_warning (G_GNUC_PRETTY_FUNCTION + "(): unable to handle positional parameters (%%n$)"); + len += 1024; /* try adding some safety padding */ + break; + + /* parse flags + */ + 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; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + v_uint = c - '0'; + c = *format; + while (c >= '0' && c <= '9') + { + 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; + case '*': + v_int = va_arg (args, 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; + case 'l': + if (!seen_l) + { + spec.mod_long = TRUE; + seen_l = TRUE; + 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 'i': + conv_len += 1; /* sign */ + /* fall through */ + case 'u': + conv_len += 4; + /* fall through */ + case 'x': + case 'X': + spec.possible_sign = TRUE; + conv_len += 10; + if (spec.mod_long && honour_longs) + conv_len *= 2; + if (spec.mod_extra_long) + conv_len *= 2; + if (spec.mod_extra_long) + { +#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); + else + (void) va_arg (args, int); + break; + case 'A': + case 'a': + /* 0x */ + conv_len += 2; + /* fall through */ + case 'g': + case 'G': + case 'e': + case 'E': + case 'f': + spec.possible_sign = TRUE; + /* n . dddddddddddddddddddddddd E +- eeee */ + conv_len += 1 + 1 + MAX (24, spec.precision) + 1 + 1 + 4; + if (may_warn && spec.mod_extra_long) + g_warning (G_GNUC_PRETTY_FUNCTION + "(): unable to handle long double, collecting double only"); +#ifdef HAVE_LONG_DOUBLE +#error need to implement special handling for long double +#endif + u_double.v_double = va_arg (args, double); + /* %f can expand up to all significant digits before '.' (308) */ + if (c == 'f' && + u_double.mpn.biased_exponent > 0 && u_double.mpn.biased_exponent < 2047) + { + 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; + case 'C': + spec.mod_long = TRUE; + /* fall through */ + case 'c': + conv_len += spec.mod_long ? MB_LEN_MAX : 1; + (void) va_arg (args, int); + 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) + { + if (may_warn) + 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': + spec.alternate_format = TRUE; + conv_len += 10; + if (honour_longs) + conv_len *= 2; + /* fall through */ + case 'n': + conv_done = TRUE; + (void) va_arg (args, void*); + break; + case 'm': + /* there's not much we can do to be clever */ + 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; + default: + if (may_warn) + g_warning (G_GNUC_PRETTY_FUNCTION + "(): unable to handle `%c' while parsing format", + c); + break; + } + conv_done |= conv_len > 0; + } + while (!conv_done); + /* handle width specifications */ + 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; +} + +guint +g_printf_string_upper_bound (const gchar *format, + va_list args) +{ + return printf_string_upper_bound (format, TRUE, args); +} + void g_messages_init (void) { diff --git a/glib/gstrfuncs.c b/glib/gstrfuncs.c index c8bf80f..99ce93a 100644 --- a/glib/gstrfuncs.c +++ b/glib/gstrfuncs.c @@ -794,143 +794,6 @@ extern const char * strsignal(int); return msg; } -guint -g_printf_string_upper_bound (const gchar* format, - va_list args) -{ - guint len = 1; - - while (*format) - { - gboolean long_int = FALSE; - gboolean extra_long = FALSE; - gchar c; - - c = *format++; - - if (c == '%') - { - gboolean done = FALSE; - - while (*format && !done) - { - switch (*format++) - { - gchar *string_arg; - - case '*': - len += va_arg (args, int); - break; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - /* add specified format length, since it might exceed the - * size we assume it to have. - */ - format -= 1; - len += strtol (format, (char**) &format, 10); - break; - case 'h': - /* ignore short int flag, since all args have at least the - * same size as an int - */ - break; - case 'l': - if (long_int) - extra_long = TRUE; /* linux specific */ - else - long_int = TRUE; - break; - case 'q': - case 'L': - long_int = TRUE; - extra_long = TRUE; - break; - case 's': - string_arg = va_arg (args, char *); - if (string_arg) - len += strlen (string_arg); - else - { - /* add enough padding to hold "(null)" identifier */ - len += 16; - } - done = TRUE; - break; - case 'd': - case 'i': - case 'o': - case 'u': - case 'x': - case 'X': -#ifdef G_HAVE_GINT64 - if (extra_long) - (void) va_arg (args, gint64); - else -#endif /* G_HAVE_GINT64 */ - { - if (long_int) - (void) va_arg (args, long); - else - (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; - case 'e': - case 'E': - case 'f': - case 'g': -#ifdef HAVE_LONG_DOUBLE - if (extra_long) - (void) va_arg (args, long double); - else -#endif /* HAVE_LONG_DOUBLE */ - (void) va_arg (args, double); - len += extra_long ? 64 : 32; - done = TRUE; - break; - case 'c': - (void) va_arg (args, int); - len += 1; - done = TRUE; - break; - case 'p': - case 'n': - (void) va_arg (args, void*); - len += 32; - done = TRUE; - break; - case '%': - len += 1; - done = TRUE; - break; - default: - /* ignore unknow/invalid flags */ - break; - } - } - } - else - len += 1; - } - - return len; -} - void g_strdown (gchar *string) { diff --git a/gmessages.c b/gmessages.c index 4179f73..5f60218 100644 --- a/gmessages.c +++ b/gmessages.c @@ -41,42 +41,9 @@ #include #endif #include +#include +#include -#ifdef G_OS_WIN32 -# define STRICT -# include -# include /* For _getpid() */ - -/* Just use stdio. If we're out of memory, we're hosed anyway. */ -#undef write - -static inline int -write (FILE *fd, - const char *buf, - int len) -{ - fwrite (buf, len, 1, fd); - - return len; -} - -static void -ensure_stdout_valid (void) -{ - HANDLE handle; - - handle = GetStdHandle (STD_OUTPUT_HANDLE); - - if (handle == INVALID_HANDLE_VALUE) - { - AllocConsole (); - freopen ("CONOUT$", "w", stdout); - } -} -#else -#define ensure_stdout_valid() /* Define as empty */ -#endif - /* --- structures --- */ typedef struct _GLogDomain GLogDomain; @@ -98,6 +65,12 @@ struct _GLogHandler }; +/* --- prototypes --- */ +static inline guint printf_string_upper_bound (const gchar *format, + gboolean may_warn, + va_list args); + + /* --- variables --- */ static GMutex* g_messages_lock = NULL; @@ -115,8 +88,40 @@ static GPrivate* g_log_depth = NULL; /* --- functions --- */ +#ifdef G_OS_WIN32 +# define STRICT +# include +# include /* For _getpid() */ +/* Just use stdio. If we're out of memory, we're hosed anyway. */ +#undef write +static inline int +write (FILE *fd, + const char *buf, + int len) +{ + fwrite (buf, len, 1, fd); + + return len; +} +static void +ensure_stdout_valid (void) +{ + HANDLE handle; + + handle = GetStdHandle (STD_OUTPUT_HANDLE); + + if (handle == INVALID_HANDLE_VALUE) + { + AllocConsole (); + freopen ("CONOUT$", "w", stdout); + } +} +#else +#define ensure_stdout_valid() /* Define as empty */ +#endif + static inline GLogDomain* -g_log_find_domain (const gchar *log_domain) +g_log_find_domain (const gchar *log_domain) { register GLogDomain *domain; @@ -286,8 +291,8 @@ g_log_set_handler (const gchar *log_domain, } void -g_log_remove_handler (const gchar *log_domain, - guint handler_id) +g_log_remove_handler (const gchar *log_domain, + guint handler_id) { register GLogDomain *domain; @@ -324,10 +329,10 @@ g_log_remove_handler (const gchar *log_domain, } void -g_logv (const gchar *log_domain, - GLogLevelFlags log_level, - const gchar *format, - va_list args1) +g_logv (const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *format, + va_list args1) { va_list args2; gchar buffer[1025]; @@ -341,7 +346,7 @@ g_logv (const gchar *log_domain, * recursively. */ G_VA_COPY (args2, args1); - if (g_printf_string_upper_bound (format, args1) < 1024) + if (printf_string_upper_bound (format, FALSE, args1) < 1024) vsprintf (buffer, format, args2); else { @@ -793,6 +798,328 @@ g_set_message_handler (GPrintFunc func) return old_message_func; } +#ifndef MB_LEN_MAX +# define MB_LEN_MAX 8 +#endif + +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; + +static inline guint +printf_string_upper_bound (const gchar *format, + gboolean may_warn, + va_list args) +{ + static const gboolean honour_longs = SIZEOF_LONG > 4 || SIZEOF_VOID_P > 4; + guint len = 1; + + if (!format) + return len; + + while (*format) + { + register gchar c = *format++; + + 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++; + switch (c) + { + GDoubleIEEE754 u_double; + guint v_uint; + gint v_int; + gchar *v_string; + + /* beware of positional parameters + */ + case '$': + if (may_warn) + g_warning (G_GNUC_PRETTY_FUNCTION + "(): unable to handle positional parameters (%%n$)"); + len += 1024; /* try adding some safety padding */ + break; + + /* parse flags + */ + 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; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + v_uint = c - '0'; + c = *format; + while (c >= '0' && c <= '9') + { + 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; + case '*': + v_int = va_arg (args, 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; + case 'l': + if (!seen_l) + { + spec.mod_long = TRUE; + seen_l = TRUE; + 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 'i': + conv_len += 1; /* sign */ + /* fall through */ + case 'u': + conv_len += 4; + /* fall through */ + case 'x': + case 'X': + spec.possible_sign = TRUE; + conv_len += 10; + if (spec.mod_long && honour_longs) + conv_len *= 2; + if (spec.mod_extra_long) + conv_len *= 2; + if (spec.mod_extra_long) + { +#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); + else + (void) va_arg (args, int); + break; + case 'A': + case 'a': + /* 0x */ + conv_len += 2; + /* fall through */ + case 'g': + case 'G': + case 'e': + case 'E': + case 'f': + spec.possible_sign = TRUE; + /* n . dddddddddddddddddddddddd E +- eeee */ + conv_len += 1 + 1 + MAX (24, spec.precision) + 1 + 1 + 4; + if (may_warn && spec.mod_extra_long) + g_warning (G_GNUC_PRETTY_FUNCTION + "(): unable to handle long double, collecting double only"); +#ifdef HAVE_LONG_DOUBLE +#error need to implement special handling for long double +#endif + u_double.v_double = va_arg (args, double); + /* %f can expand up to all significant digits before '.' (308) */ + if (c == 'f' && + u_double.mpn.biased_exponent > 0 && u_double.mpn.biased_exponent < 2047) + { + 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; + case 'C': + spec.mod_long = TRUE; + /* fall through */ + case 'c': + conv_len += spec.mod_long ? MB_LEN_MAX : 1; + (void) va_arg (args, int); + 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) + { + if (may_warn) + 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': + spec.alternate_format = TRUE; + conv_len += 10; + if (honour_longs) + conv_len *= 2; + /* fall through */ + case 'n': + conv_done = TRUE; + (void) va_arg (args, void*); + break; + case 'm': + /* there's not much we can do to be clever */ + 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; + default: + if (may_warn) + g_warning (G_GNUC_PRETTY_FUNCTION + "(): unable to handle `%c' while parsing format", + c); + break; + } + conv_done |= conv_len > 0; + } + while (!conv_done); + /* handle width specifications */ + 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; +} + +guint +g_printf_string_upper_bound (const gchar *format, + va_list args) +{ + return printf_string_upper_bound (format, TRUE, args); +} + void g_messages_init (void) { diff --git a/gstrfuncs.c b/gstrfuncs.c index c8bf80f..99ce93a 100644 --- a/gstrfuncs.c +++ b/gstrfuncs.c @@ -794,143 +794,6 @@ extern const char * strsignal(int); return msg; } -guint -g_printf_string_upper_bound (const gchar* format, - va_list args) -{ - guint len = 1; - - while (*format) - { - gboolean long_int = FALSE; - gboolean extra_long = FALSE; - gchar c; - - c = *format++; - - if (c == '%') - { - gboolean done = FALSE; - - while (*format && !done) - { - switch (*format++) - { - gchar *string_arg; - - case '*': - len += va_arg (args, int); - break; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - /* add specified format length, since it might exceed the - * size we assume it to have. - */ - format -= 1; - len += strtol (format, (char**) &format, 10); - break; - case 'h': - /* ignore short int flag, since all args have at least the - * same size as an int - */ - break; - case 'l': - if (long_int) - extra_long = TRUE; /* linux specific */ - else - long_int = TRUE; - break; - case 'q': - case 'L': - long_int = TRUE; - extra_long = TRUE; - break; - case 's': - string_arg = va_arg (args, char *); - if (string_arg) - len += strlen (string_arg); - else - { - /* add enough padding to hold "(null)" identifier */ - len += 16; - } - done = TRUE; - break; - case 'd': - case 'i': - case 'o': - case 'u': - case 'x': - case 'X': -#ifdef G_HAVE_GINT64 - if (extra_long) - (void) va_arg (args, gint64); - else -#endif /* G_HAVE_GINT64 */ - { - if (long_int) - (void) va_arg (args, long); - else - (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; - case 'e': - case 'E': - case 'f': - case 'g': -#ifdef HAVE_LONG_DOUBLE - if (extra_long) - (void) va_arg (args, long double); - else -#endif /* HAVE_LONG_DOUBLE */ - (void) va_arg (args, double); - len += extra_long ? 64 : 32; - done = TRUE; - break; - case 'c': - (void) va_arg (args, int); - len += 1; - done = TRUE; - break; - case 'p': - case 'n': - (void) va_arg (args, void*); - len += 32; - done = TRUE; - break; - case '%': - len += 1; - done = TRUE; - break; - default: - /* ignore unknow/invalid flags */ - break; - } - } - } - else - len += 1; - } - - return len; -} - void g_strdown (gchar *string) { -- 2.7.4