diff --git a/ChangeLog b/ChangeLog index dc7807b36..fb9c4a568 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 dc7807b36..fb9c4a568 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 dc7807b36..fb9c4a568 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 dc7807b36..fb9c4a568 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 dc7807b36..fb9c4a568 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 dc7807b36..fb9c4a568 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 dc7807b36..fb9c4a568 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 dc7807b36..fb9c4a568 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 f0b6937b9..c7167830d 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 342657852..7b7a77b34 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 4300fd3e0..64670120b 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 4300fd3e0..64670120b 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 4179f73f9..5f60218bf 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 c8bf80f51..99ce93ac4 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 4179f73f9..5f60218bf 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 c8bf80f51..99ce93ac4 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) {