completly new implementation for printf string upper bounds calculation.

Tue Oct 12 12:16:12 1999  Tim Janik  <timj@gtk.org>

        * 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  <timj@gtk.org>

        * gstrfuncs.c: nuked old g_printf_string_upper_bound() version.

Tue Oct 12 03:34:40 1999  Tim Janik  <timj@gtk.org>

        * 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  <timj@gtk.org>

        * configure.in: added additional checks to figure sizes of size_t,
        ptrdiff_t and intmax_t (required by g_printf_string_upper_bound).
This commit is contained in:
Tim Janik 1999-10-12 12:08:13 +00:00 committed by Tim Janik
parent acbe34e51a
commit 30a1e1addb
16 changed files with 1209 additions and 362 deletions

View File

@ -1,3 +1,41 @@
Tue Oct 12 12:16:12 1999 Tim Janik <timj@gtk.org>
* 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 <timj@gtk.org>
* gstrfuncs.c: nuked old g_printf_string_upper_bound() version.
Tue Oct 12 03:34:40 1999 Tim Janik <timj@gtk.org>
* 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 <timj@gtk.org>
* 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 <yosh@gimp.org>
* configure.in: blah. use G_WITH_CYGWIN instead of G_HAVE_CYGWIN

View File

@ -1,3 +1,41 @@
Tue Oct 12 12:16:12 1999 Tim Janik <timj@gtk.org>
* 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 <timj@gtk.org>
* gstrfuncs.c: nuked old g_printf_string_upper_bound() version.
Tue Oct 12 03:34:40 1999 Tim Janik <timj@gtk.org>
* 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 <timj@gtk.org>
* 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 <yosh@gimp.org>
* configure.in: blah. use G_WITH_CYGWIN instead of G_HAVE_CYGWIN

View File

@ -1,3 +1,41 @@
Tue Oct 12 12:16:12 1999 Tim Janik <timj@gtk.org>
* 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 <timj@gtk.org>
* gstrfuncs.c: nuked old g_printf_string_upper_bound() version.
Tue Oct 12 03:34:40 1999 Tim Janik <timj@gtk.org>
* 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 <timj@gtk.org>
* 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 <yosh@gimp.org>
* configure.in: blah. use G_WITH_CYGWIN instead of G_HAVE_CYGWIN

View File

@ -1,3 +1,41 @@
Tue Oct 12 12:16:12 1999 Tim Janik <timj@gtk.org>
* 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 <timj@gtk.org>
* gstrfuncs.c: nuked old g_printf_string_upper_bound() version.
Tue Oct 12 03:34:40 1999 Tim Janik <timj@gtk.org>
* 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 <timj@gtk.org>
* 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 <yosh@gimp.org>
* configure.in: blah. use G_WITH_CYGWIN instead of G_HAVE_CYGWIN

View File

@ -1,3 +1,41 @@
Tue Oct 12 12:16:12 1999 Tim Janik <timj@gtk.org>
* 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 <timj@gtk.org>
* gstrfuncs.c: nuked old g_printf_string_upper_bound() version.
Tue Oct 12 03:34:40 1999 Tim Janik <timj@gtk.org>
* 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 <timj@gtk.org>
* 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 <yosh@gimp.org>
* configure.in: blah. use G_WITH_CYGWIN instead of G_HAVE_CYGWIN

View File

@ -1,3 +1,41 @@
Tue Oct 12 12:16:12 1999 Tim Janik <timj@gtk.org>
* 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 <timj@gtk.org>
* gstrfuncs.c: nuked old g_printf_string_upper_bound() version.
Tue Oct 12 03:34:40 1999 Tim Janik <timj@gtk.org>
* 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 <timj@gtk.org>
* 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 <yosh@gimp.org>
* configure.in: blah. use G_WITH_CYGWIN instead of G_HAVE_CYGWIN

View File

@ -1,3 +1,41 @@
Tue Oct 12 12:16:12 1999 Tim Janik <timj@gtk.org>
* 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 <timj@gtk.org>
* gstrfuncs.c: nuked old g_printf_string_upper_bound() version.
Tue Oct 12 03:34:40 1999 Tim Janik <timj@gtk.org>
* 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 <timj@gtk.org>
* 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 <yosh@gimp.org>
* configure.in: blah. use G_WITH_CYGWIN instead of G_HAVE_CYGWIN

View File

@ -1,3 +1,41 @@
Tue Oct 12 12:16:12 1999 Tim Janik <timj@gtk.org>
* 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 <timj@gtk.org>
* gstrfuncs.c: nuked old g_printf_string_upper_bound() version.
Tue Oct 12 03:34:40 1999 Tim Janik <timj@gtk.org>
* 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 <timj@gtk.org>
* 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 <yosh@gimp.org>
* configure.in: blah. use G_WITH_CYGWIN instead of G_HAVE_CYGWIN

View File

@ -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

View File

@ -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 <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
"]
if test "x$ac_cv_header_stdint_h" = "xyes"; then
size_includes=["$size_includes
#include <stdint.h>
"]
fi
if test "x$ac_cv_header_unistd_h" = "xyes"; then
size_includes=["$size_includes
#include <unistd.h>
"]
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)

68
glib.h
View File

@ -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);

View File

@ -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);

View File

@ -41,42 +41,9 @@
#include <unistd.h>
#endif
#include <signal.h>
#include <locale.h>
#include <errno.h>
#ifdef G_OS_WIN32
# define STRICT
# include <windows.h>
# include <process.h> /* 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 <windows.h>
# include <process.h> /* 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)
{

View File

@ -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)
{

View File

@ -41,42 +41,9 @@
#include <unistd.h>
#endif
#include <signal.h>
#include <locale.h>
#include <errno.h>
#ifdef G_OS_WIN32
# define STRICT
# include <windows.h>
# include <process.h> /* 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 <windows.h>
# include <process.h> /* 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)
{

View File

@ -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)
{