mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-11 15:06:14 +01:00
Include a printf implementation supporting C99 snprintf and SUS
positional parameters: (#79488) * glib/gstrfuncs.c: * glib/gspawn-win32.c: * glib/gscanner.c: * glib/gconvert.c: * glib/gbacktrace.c: Use _g_printf wrappers. * glib/gutils.c (g_vsnprintf): Simplify, since we can assume C99 snprintf semantics now. * glib/gmessages.c (printf_string_upper_bound): No longer needed, since we can assume C99 snprintf semantics now. (g_logv): Simplify. * acinclude.m4 (AC_FUNC_PRINTF_UNIX98): New macro to check wether printf supports SUS positional parameters. * configure.in: New option --enable-included-printf to force compilation of trio; otherwise trio is compiled if the system printf misses either C99 snprintf semantics of SUS positional parameters. * glib/Makefile.am (SUBDIRS): Conditionally compile trio. (libglib_2_0_la_SOURCES): Add gprintf.c and gprintfint.h. (glibsubinclude_HEADERS): Add gprintf.h. * glib/gprintfint.h: New private wrapping either system printf or trio printf variants in _g_printf wrappers for use inside glib. * glib/gprintf.h: New public header declaring g_printf variants. * glib/gprintf.c: Corresponding implementations. * glib/trio/*: New directory, containing the trio-1.9 sources. * glib/tmpl/string_utils.sgml: Add note on including gprintf.h, move some docs inline. * glib/glib-sections.txt: Add g_printf, g_vprintf, g_fprintf, g_vfprintf, g_sprintf, g_vsprintf.
This commit is contained in:
parent
dc645ce354
commit
bc54ea6edf
38
ChangeLog
38
ChangeLog
@ -1,3 +1,41 @@
|
||||
2002-11-21 Matthias Clasen <maclas@gmx.de>
|
||||
|
||||
Include a printf implementation supporting C99 snprintf and SUS
|
||||
positional parameters: (#79488)
|
||||
|
||||
* glib/gstrfuncs.c:
|
||||
* glib/gspawn-win32.c:
|
||||
* glib/gscanner.c:
|
||||
* glib/gconvert.c:
|
||||
* glib/gbacktrace.c: Use _g_printf wrappers.
|
||||
|
||||
* glib/gutils.c (g_vsnprintf): Simplify, since we can assume C99
|
||||
snprintf semantics now.
|
||||
|
||||
* glib/gmessages.c (printf_string_upper_bound): No longer needed,
|
||||
since we can assume C99 snprintf semantics now.
|
||||
(g_logv): Simplify.
|
||||
|
||||
* acinclude.m4 (AC_FUNC_PRINTF_UNIX98): New macro to check wether
|
||||
printf supports SUS positional parameters.
|
||||
|
||||
* configure.in: New option --enable-included-printf to force
|
||||
compilation of trio; otherwise trio is compiled if the system
|
||||
printf misses either C99 snprintf semantics of SUS positional
|
||||
parameters.
|
||||
|
||||
* glib/Makefile.am (SUBDIRS): Conditionally compile trio.
|
||||
(libglib_2_0_la_SOURCES): Add gprintf.c and gprintfint.h.
|
||||
(glibsubinclude_HEADERS): Add gprintf.h.
|
||||
|
||||
* glib/gprintfint.h: New private wrapping either system printf
|
||||
or trio printf variants in _g_printf wrappers for use inside glib.
|
||||
|
||||
* glib/gprintf.h: New public header declaring g_printf variants.
|
||||
* glib/gprintf.c: Corresponding implementations.
|
||||
|
||||
* glib/trio/*: New directory, containing the trio-1.9 sources.
|
||||
|
||||
2002-11-20 Matthias Clasen <maclas@gmx.de>
|
||||
|
||||
* glib/gmessages.h (g_return_if_fail):
|
||||
|
@ -1,3 +1,41 @@
|
||||
2002-11-21 Matthias Clasen <maclas@gmx.de>
|
||||
|
||||
Include a printf implementation supporting C99 snprintf and SUS
|
||||
positional parameters: (#79488)
|
||||
|
||||
* glib/gstrfuncs.c:
|
||||
* glib/gspawn-win32.c:
|
||||
* glib/gscanner.c:
|
||||
* glib/gconvert.c:
|
||||
* glib/gbacktrace.c: Use _g_printf wrappers.
|
||||
|
||||
* glib/gutils.c (g_vsnprintf): Simplify, since we can assume C99
|
||||
snprintf semantics now.
|
||||
|
||||
* glib/gmessages.c (printf_string_upper_bound): No longer needed,
|
||||
since we can assume C99 snprintf semantics now.
|
||||
(g_logv): Simplify.
|
||||
|
||||
* acinclude.m4 (AC_FUNC_PRINTF_UNIX98): New macro to check wether
|
||||
printf supports SUS positional parameters.
|
||||
|
||||
* configure.in: New option --enable-included-printf to force
|
||||
compilation of trio; otherwise trio is compiled if the system
|
||||
printf misses either C99 snprintf semantics of SUS positional
|
||||
parameters.
|
||||
|
||||
* glib/Makefile.am (SUBDIRS): Conditionally compile trio.
|
||||
(libglib_2_0_la_SOURCES): Add gprintf.c and gprintfint.h.
|
||||
(glibsubinclude_HEADERS): Add gprintf.h.
|
||||
|
||||
* glib/gprintfint.h: New private wrapping either system printf
|
||||
or trio printf variants in _g_printf wrappers for use inside glib.
|
||||
|
||||
* glib/gprintf.h: New public header declaring g_printf variants.
|
||||
* glib/gprintf.c: Corresponding implementations.
|
||||
|
||||
* glib/trio/*: New directory, containing the trio-1.9 sources.
|
||||
|
||||
2002-11-20 Matthias Clasen <maclas@gmx.de>
|
||||
|
||||
* glib/gmessages.h (g_return_if_fail):
|
||||
|
@ -1,3 +1,41 @@
|
||||
2002-11-21 Matthias Clasen <maclas@gmx.de>
|
||||
|
||||
Include a printf implementation supporting C99 snprintf and SUS
|
||||
positional parameters: (#79488)
|
||||
|
||||
* glib/gstrfuncs.c:
|
||||
* glib/gspawn-win32.c:
|
||||
* glib/gscanner.c:
|
||||
* glib/gconvert.c:
|
||||
* glib/gbacktrace.c: Use _g_printf wrappers.
|
||||
|
||||
* glib/gutils.c (g_vsnprintf): Simplify, since we can assume C99
|
||||
snprintf semantics now.
|
||||
|
||||
* glib/gmessages.c (printf_string_upper_bound): No longer needed,
|
||||
since we can assume C99 snprintf semantics now.
|
||||
(g_logv): Simplify.
|
||||
|
||||
* acinclude.m4 (AC_FUNC_PRINTF_UNIX98): New macro to check wether
|
||||
printf supports SUS positional parameters.
|
||||
|
||||
* configure.in: New option --enable-included-printf to force
|
||||
compilation of trio; otherwise trio is compiled if the system
|
||||
printf misses either C99 snprintf semantics of SUS positional
|
||||
parameters.
|
||||
|
||||
* glib/Makefile.am (SUBDIRS): Conditionally compile trio.
|
||||
(libglib_2_0_la_SOURCES): Add gprintf.c and gprintfint.h.
|
||||
(glibsubinclude_HEADERS): Add gprintf.h.
|
||||
|
||||
* glib/gprintfint.h: New private wrapping either system printf
|
||||
or trio printf variants in _g_printf wrappers for use inside glib.
|
||||
|
||||
* glib/gprintf.h: New public header declaring g_printf variants.
|
||||
* glib/gprintf.c: Corresponding implementations.
|
||||
|
||||
* glib/trio/*: New directory, containing the trio-1.9 sources.
|
||||
|
||||
2002-11-20 Matthias Clasen <maclas@gmx.de>
|
||||
|
||||
* glib/gmessages.h (g_return_if_fail):
|
||||
|
@ -1,3 +1,41 @@
|
||||
2002-11-21 Matthias Clasen <maclas@gmx.de>
|
||||
|
||||
Include a printf implementation supporting C99 snprintf and SUS
|
||||
positional parameters: (#79488)
|
||||
|
||||
* glib/gstrfuncs.c:
|
||||
* glib/gspawn-win32.c:
|
||||
* glib/gscanner.c:
|
||||
* glib/gconvert.c:
|
||||
* glib/gbacktrace.c: Use _g_printf wrappers.
|
||||
|
||||
* glib/gutils.c (g_vsnprintf): Simplify, since we can assume C99
|
||||
snprintf semantics now.
|
||||
|
||||
* glib/gmessages.c (printf_string_upper_bound): No longer needed,
|
||||
since we can assume C99 snprintf semantics now.
|
||||
(g_logv): Simplify.
|
||||
|
||||
* acinclude.m4 (AC_FUNC_PRINTF_UNIX98): New macro to check wether
|
||||
printf supports SUS positional parameters.
|
||||
|
||||
* configure.in: New option --enable-included-printf to force
|
||||
compilation of trio; otherwise trio is compiled if the system
|
||||
printf misses either C99 snprintf semantics of SUS positional
|
||||
parameters.
|
||||
|
||||
* glib/Makefile.am (SUBDIRS): Conditionally compile trio.
|
||||
(libglib_2_0_la_SOURCES): Add gprintf.c and gprintfint.h.
|
||||
(glibsubinclude_HEADERS): Add gprintf.h.
|
||||
|
||||
* glib/gprintfint.h: New private wrapping either system printf
|
||||
or trio printf variants in _g_printf wrappers for use inside glib.
|
||||
|
||||
* glib/gprintf.h: New public header declaring g_printf variants.
|
||||
* glib/gprintf.c: Corresponding implementations.
|
||||
|
||||
* glib/trio/*: New directory, containing the trio-1.9 sources.
|
||||
|
||||
2002-11-20 Matthias Clasen <maclas@gmx.de>
|
||||
|
||||
* glib/gmessages.h (g_return_if_fail):
|
||||
|
@ -1,3 +1,41 @@
|
||||
2002-11-21 Matthias Clasen <maclas@gmx.de>
|
||||
|
||||
Include a printf implementation supporting C99 snprintf and SUS
|
||||
positional parameters: (#79488)
|
||||
|
||||
* glib/gstrfuncs.c:
|
||||
* glib/gspawn-win32.c:
|
||||
* glib/gscanner.c:
|
||||
* glib/gconvert.c:
|
||||
* glib/gbacktrace.c: Use _g_printf wrappers.
|
||||
|
||||
* glib/gutils.c (g_vsnprintf): Simplify, since we can assume C99
|
||||
snprintf semantics now.
|
||||
|
||||
* glib/gmessages.c (printf_string_upper_bound): No longer needed,
|
||||
since we can assume C99 snprintf semantics now.
|
||||
(g_logv): Simplify.
|
||||
|
||||
* acinclude.m4 (AC_FUNC_PRINTF_UNIX98): New macro to check wether
|
||||
printf supports SUS positional parameters.
|
||||
|
||||
* configure.in: New option --enable-included-printf to force
|
||||
compilation of trio; otherwise trio is compiled if the system
|
||||
printf misses either C99 snprintf semantics of SUS positional
|
||||
parameters.
|
||||
|
||||
* glib/Makefile.am (SUBDIRS): Conditionally compile trio.
|
||||
(libglib_2_0_la_SOURCES): Add gprintf.c and gprintfint.h.
|
||||
(glibsubinclude_HEADERS): Add gprintf.h.
|
||||
|
||||
* glib/gprintfint.h: New private wrapping either system printf
|
||||
or trio printf variants in _g_printf wrappers for use inside glib.
|
||||
|
||||
* glib/gprintf.h: New public header declaring g_printf variants.
|
||||
* glib/gprintf.c: Corresponding implementations.
|
||||
|
||||
* glib/trio/*: New directory, containing the trio-1.9 sources.
|
||||
|
||||
2002-11-20 Matthias Clasen <maclas@gmx.de>
|
||||
|
||||
* glib/gmessages.h (g_return_if_fail):
|
||||
|
@ -1,3 +1,41 @@
|
||||
2002-11-21 Matthias Clasen <maclas@gmx.de>
|
||||
|
||||
Include a printf implementation supporting C99 snprintf and SUS
|
||||
positional parameters: (#79488)
|
||||
|
||||
* glib/gstrfuncs.c:
|
||||
* glib/gspawn-win32.c:
|
||||
* glib/gscanner.c:
|
||||
* glib/gconvert.c:
|
||||
* glib/gbacktrace.c: Use _g_printf wrappers.
|
||||
|
||||
* glib/gutils.c (g_vsnprintf): Simplify, since we can assume C99
|
||||
snprintf semantics now.
|
||||
|
||||
* glib/gmessages.c (printf_string_upper_bound): No longer needed,
|
||||
since we can assume C99 snprintf semantics now.
|
||||
(g_logv): Simplify.
|
||||
|
||||
* acinclude.m4 (AC_FUNC_PRINTF_UNIX98): New macro to check wether
|
||||
printf supports SUS positional parameters.
|
||||
|
||||
* configure.in: New option --enable-included-printf to force
|
||||
compilation of trio; otherwise trio is compiled if the system
|
||||
printf misses either C99 snprintf semantics of SUS positional
|
||||
parameters.
|
||||
|
||||
* glib/Makefile.am (SUBDIRS): Conditionally compile trio.
|
||||
(libglib_2_0_la_SOURCES): Add gprintf.c and gprintfint.h.
|
||||
(glibsubinclude_HEADERS): Add gprintf.h.
|
||||
|
||||
* glib/gprintfint.h: New private wrapping either system printf
|
||||
or trio printf variants in _g_printf wrappers for use inside glib.
|
||||
|
||||
* glib/gprintf.h: New public header declaring g_printf variants.
|
||||
* glib/gprintf.c: Corresponding implementations.
|
||||
|
||||
* glib/trio/*: New directory, containing the trio-1.9 sources.
|
||||
|
||||
2002-11-20 Matthias Clasen <maclas@gmx.de>
|
||||
|
||||
* glib/gmessages.h (g_return_if_fail):
|
||||
|
@ -1,3 +1,41 @@
|
||||
2002-11-21 Matthias Clasen <maclas@gmx.de>
|
||||
|
||||
Include a printf implementation supporting C99 snprintf and SUS
|
||||
positional parameters: (#79488)
|
||||
|
||||
* glib/gstrfuncs.c:
|
||||
* glib/gspawn-win32.c:
|
||||
* glib/gscanner.c:
|
||||
* glib/gconvert.c:
|
||||
* glib/gbacktrace.c: Use _g_printf wrappers.
|
||||
|
||||
* glib/gutils.c (g_vsnprintf): Simplify, since we can assume C99
|
||||
snprintf semantics now.
|
||||
|
||||
* glib/gmessages.c (printf_string_upper_bound): No longer needed,
|
||||
since we can assume C99 snprintf semantics now.
|
||||
(g_logv): Simplify.
|
||||
|
||||
* acinclude.m4 (AC_FUNC_PRINTF_UNIX98): New macro to check wether
|
||||
printf supports SUS positional parameters.
|
||||
|
||||
* configure.in: New option --enable-included-printf to force
|
||||
compilation of trio; otherwise trio is compiled if the system
|
||||
printf misses either C99 snprintf semantics of SUS positional
|
||||
parameters.
|
||||
|
||||
* glib/Makefile.am (SUBDIRS): Conditionally compile trio.
|
||||
(libglib_2_0_la_SOURCES): Add gprintf.c and gprintfint.h.
|
||||
(glibsubinclude_HEADERS): Add gprintf.h.
|
||||
|
||||
* glib/gprintfint.h: New private wrapping either system printf
|
||||
or trio printf variants in _g_printf wrappers for use inside glib.
|
||||
|
||||
* glib/gprintf.h: New public header declaring g_printf variants.
|
||||
* glib/gprintf.c: Corresponding implementations.
|
||||
|
||||
* glib/trio/*: New directory, containing the trio-1.9 sources.
|
||||
|
||||
2002-11-20 Matthias Clasen <maclas@gmx.de>
|
||||
|
||||
* glib/gmessages.h (g_return_if_fail):
|
||||
|
34
acinclude.m4
34
acinclude.m4
@ -327,3 +327,37 @@ if test $ac_cv_func_vsnprintf_c99 = yes; then
|
||||
fi
|
||||
])# AC_FUNC_VSNPRINTF_C99
|
||||
|
||||
|
||||
dnl @synopsis AC_FUNC_PRINTF_UNIX98
|
||||
dnl
|
||||
dnl Check whether the printf() family supports Unix98 %n$ positional parameters
|
||||
dnl
|
||||
AC_DEFUN([AC_FUNC_PRINTF_UNIX98],
|
||||
[AC_CACHE_CHECK(whether printf supports positional parameters,
|
||||
ac_cv_func_printf_unix98,
|
||||
[AC_TRY_RUN(
|
||||
[#include <stdio.h>
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
char buffer[128];
|
||||
|
||||
sprintf (buffer, "%2\$d %3\$d %1\$d", 1, 2, 3);
|
||||
if (strcmp ("2 3 1", buffer) == 0)
|
||||
exit (0);
|
||||
exit (1);
|
||||
}], ac_cv_func_printf_unix98=yes, ac_cv_func_printf_unix98=no, ac_cv_func_printf_unix98=no)])
|
||||
dnl Note that the default is to be pessimistic in the case of cross compilation.
|
||||
dnl If you know that the target printf() supports positional parameters, you can get around
|
||||
dnl this by setting ac_func_printf_unix98 to yes, as described in the Autoconf manual.
|
||||
if test $ac_cv_func_printf_unix98 = yes; then
|
||||
AC_DEFINE(HAVE_UNIX98_PRINTF, 1,
|
||||
[Define if your printf function family supports positional parameters
|
||||
as specified by Unix98.])
|
||||
fi
|
||||
])# AC_FUNC_PRINTF_UNIX98
|
||||
|
||||
|
||||
|
||||
|
||||
|
27
configure.in
27
configure.in
@ -712,6 +712,32 @@ AC_MSG_RESULT(unsigned $glib_size_type)
|
||||
AC_CHECK_FUNCS(lstat strerror strsignal memmove mkstemp vsnprintf stpcpy strcasecmp strncasecmp poll getcwd nanosleep vasprintf unsetenv getc_unlocked)
|
||||
|
||||
AC_FUNC_VSNPRINTF_C99
|
||||
AC_FUNC_PRINTF_UNIX98
|
||||
|
||||
#
|
||||
# Check whether to use trio printf
|
||||
#
|
||||
|
||||
AC_ARG_ENABLE(included-printf, [ --enable-included-printf use included printf [default=auto]], enable_trio="$enableval")
|
||||
|
||||
if test "$enable_trio" != "no" ; then
|
||||
if test "$ac_cv_func_vsnprintf_c99" != "yes" ; then
|
||||
enable_trio = yes
|
||||
fi
|
||||
if test "$ac_cv_func_printf_unix98" != "yes" ; then
|
||||
enable_trio = yes
|
||||
fi
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(HAVE_GOOD_PRINTF, test "$enable_trio" != "yes")
|
||||
if test "$enable_trio" != "yes" ; then
|
||||
AC_DEFINE(HAVE_GOOD_PRINTF,1,[define to use system printf])
|
||||
AC_DEFINE(HAVE_VASPRINTF,1)
|
||||
AC_DEFINE(HAVE_C99_VSNPRINTF,1)
|
||||
AC_DEFINE(HAVE_UNIX98_PRINTF,1)
|
||||
else
|
||||
AC_DEFINE(HAVE_GOOD_PRINTF,0)
|
||||
fi
|
||||
|
||||
# Check if bcopy can be used for overlapping copies, if memmove isn't found.
|
||||
# The check is borrowed from the PERL Configure script.
|
||||
@ -2355,6 +2381,7 @@ build/win32/Makefile
|
||||
build/win32/dirent/Makefile
|
||||
glib/Makefile
|
||||
glib/libcharset/Makefile
|
||||
glib/trio/Makefile
|
||||
gmodule/gmoduleconf.h
|
||||
gmodule/Makefile
|
||||
gobject/Makefile
|
||||
|
@ -1,3 +1,11 @@
|
||||
2002-11-21 Matthias Clasen <maclas@gmx.de>
|
||||
|
||||
* glib/tmpl/string_utils.sgml: Add note on including gprintf.h,
|
||||
move some docs inline.
|
||||
|
||||
* glib/glib-sections.txt: Add g_printf, g_vprintf, g_fprintf,
|
||||
g_vfprintf, g_sprintf, g_vsprintf.
|
||||
|
||||
2002-11-20 Matthias Clasen <maclas@gmx.de>
|
||||
|
||||
* glib/tmpl/macros_misc.sgml: Document G_LIKELY, G_UNLIKELY.
|
||||
|
@ -896,6 +896,12 @@ g_strlcat
|
||||
<SUBSECTION>
|
||||
g_strdup_printf
|
||||
g_strdup_vprintf
|
||||
g_printf
|
||||
g_vprintf
|
||||
g_fprintf
|
||||
g_vfprintf
|
||||
g_sprintf
|
||||
g_vsprintf
|
||||
g_snprintf
|
||||
g_vsnprintf
|
||||
g_printf_string_upper_bound
|
||||
|
@ -9,6 +9,15 @@ various string-related functions.
|
||||
This section describes a number of utility functions for creating,
|
||||
duplicating, and manipulating strings.
|
||||
</para>
|
||||
<para>
|
||||
Note that the functions g_printf(), g_fprintf(), g_sprintf(), g_snprintf(),
|
||||
g_vprintf(), g_vfprintf(), g_vsprintf() and g_vsnprintf() are declared in
|
||||
the header <filename>gprintf.h</filename> which is <emphasis>not</emphasis>
|
||||
included in <filename>glib.h</filename> (otherwise using
|
||||
<filename>glib.h</filename> would drag in <filename>stdio.h</filename>), so
|
||||
you'll have to explicitly include <literal><glib/gprintf.h></literal>
|
||||
in order to use the printf() functions.
|
||||
</para>
|
||||
|
||||
<!-- ##### SECTION See_Also ##### -->
|
||||
<para>
|
||||
@ -180,78 +189,90 @@ The returned string should be freed when no longer needed.
|
||||
@Returns: a newly-allocated string holding the result.
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_printf ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@format:
|
||||
@Varargs:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_vprintf ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@format:
|
||||
@args:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_fprintf ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@file:
|
||||
@format:
|
||||
@Varargs:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_vfprintf ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@file:
|
||||
@format:
|
||||
@args:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_sprintf ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@string:
|
||||
@format:
|
||||
@Varargs:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_vsprintf ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@string:
|
||||
@format:
|
||||
@args:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_snprintf ##### -->
|
||||
<para>
|
||||
A safer form of the standard <function>sprintf()</function> function.
|
||||
The output is guaranteed to not exceed @n characters (including the
|
||||
terminating nul character), so it is easy to ensure that a buffer overflow
|
||||
cannot occur.
|
||||
</para>
|
||||
<para>
|
||||
See also g_strdup_printf().
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
In versions of GLib prior to 1.2.3, this function may return -1 if the output
|
||||
was truncated, and the truncated string may not be nul-terminated.
|
||||
In versions prior to 1.3.12, this function returns the length of the output
|
||||
string.
|
||||
</para>
|
||||
</note>
|
||||
<note>
|
||||
<para>
|
||||
The return value of g_snprintf() conforms to the <function>snprintf()</function>
|
||||
function as standardized in ISO C99. Note that this is different from
|
||||
traditional <function>snprintf()</function>, which returns the length of
|
||||
the output string.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
@string: the buffer to hold the output.
|
||||
@n: the maximum number of characters to produce (including the terminating nul
|
||||
character).
|
||||
@format: the format string. See the <function>sprintf()</function>.
|
||||
documentation.
|
||||
@Varargs: the arguments to insert in the output.
|
||||
@Returns: the number of characters which would be produced if the buffer was
|
||||
large enough.
|
||||
@string:
|
||||
@n:
|
||||
@format:
|
||||
@Varargs:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_vsnprintf ##### -->
|
||||
<para>
|
||||
A safer form of the standard <function>vsprintf()</function> function.
|
||||
The output is guaranteed to not exceed @n characters (including the
|
||||
terminating nul character), so it is easy to ensure that a buffer overflow
|
||||
cannot occur.
|
||||
</para>
|
||||
<para>
|
||||
See also g_strdup_vprintf().
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
In versions of GLib prior to 1.2.3, this function may return -1 if the output
|
||||
was truncated, and the truncated string may not be nul-terminated.
|
||||
In versions prior to 1.3.12, this function returns the length of the output
|
||||
string.
|
||||
</para>
|
||||
</note>
|
||||
<note>
|
||||
<para>
|
||||
The return value of g_vsnprintf() conforms to the <function>vsnprintf()</function>
|
||||
function as standardized in ISO C99. Note that this is different from
|
||||
traditional <function>vsnprintf()</function>, which returns the length of
|
||||
the output string.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
@string: the buffer to hold the output.
|
||||
@n: the maximum number of characters to produce (including the terminating nul
|
||||
character).
|
||||
@format: the format string. See the <function>sprintf()</function>
|
||||
documentation.
|
||||
@args: the list of arguments to insert in the output.
|
||||
@Returns: the number of characters which would be produced if the buffer was
|
||||
large enough.
|
||||
@string:
|
||||
@n:
|
||||
@format:
|
||||
@args:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_printf_string_upper_bound ##### -->
|
||||
|
@ -1,6 +1,13 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
SUBDIRS=libcharset
|
||||
if HAVE_GOOD_PRINTF
|
||||
else
|
||||
TRIO_SUBDIR = trio
|
||||
endif
|
||||
|
||||
SUBDIRS = libcharset $(TRIO_SUBDIR)
|
||||
|
||||
DIST_SUBDIRS = libcharset trio
|
||||
|
||||
INCLUDES = -I$(top_srcdir) -DG_LOG_DOMAIN=\"GLib\" \
|
||||
@GLIB_DEBUG_FLAGS@ -DG_DISABLE_DEPRECATED -DGLIB_COMPILATION
|
||||
@ -82,7 +89,9 @@ libglib_2_0_la_SOURCES = \
|
||||
gunidecomp.h \
|
||||
gunidecomp.c \
|
||||
gutils.c \
|
||||
gdebug.h
|
||||
gdebug.h \
|
||||
gprintf.c \
|
||||
gprintfint.h
|
||||
|
||||
EXTRA_libglib_2_0_la_SOURCES = \
|
||||
giounix.c \
|
||||
@ -140,7 +149,8 @@ glibsubinclude_HEADERS = \
|
||||
gtypes.h \
|
||||
gunicode.h \
|
||||
gutils.h \
|
||||
gwin32.h
|
||||
gwin32.h \
|
||||
gprintf.h
|
||||
|
||||
install-data-local: install-ms-lib install-libtool-import-lib
|
||||
@if test -f $(glibincludedir)/glist.h ; then \
|
||||
|
@ -38,6 +38,8 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "glib.h"
|
||||
#include "gprintfint.h"
|
||||
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
@ -98,19 +100,19 @@ g_on_error_query (const gchar *prg_name)
|
||||
retry:
|
||||
|
||||
if (prg_name)
|
||||
fprintf (stdout,
|
||||
"%s (pid:%u): %s%s%s: ",
|
||||
prg_name,
|
||||
(guint) getpid (),
|
||||
query1,
|
||||
query2,
|
||||
query3);
|
||||
_g_fprintf (stdout,
|
||||
"%s (pid:%u): %s%s%s: ",
|
||||
prg_name,
|
||||
(guint) getpid (),
|
||||
query1,
|
||||
query2,
|
||||
query3);
|
||||
else
|
||||
fprintf (stdout,
|
||||
"(process:%u): %s%s: ",
|
||||
(guint) getpid (),
|
||||
query1,
|
||||
query3);
|
||||
_g_fprintf (stdout,
|
||||
"(process:%u): %s%s: ",
|
||||
(guint) getpid (),
|
||||
query1,
|
||||
query3);
|
||||
fflush (stdout);
|
||||
|
||||
if (isatty(0) && isatty(1))
|
||||
@ -163,7 +165,7 @@ g_on_error_stack_trace (const gchar *prg_name)
|
||||
if (!prg_name)
|
||||
return;
|
||||
|
||||
sprintf (buf, "%u", (guint) getpid ());
|
||||
_g_sprintf (buf, "%u", (guint) getpid ());
|
||||
|
||||
args[1] = (gchar*) prg_name;
|
||||
args[2] = buf;
|
||||
@ -276,7 +278,7 @@ stack_trace (char **args)
|
||||
if ((c == '\n') || (c == '\r'))
|
||||
{
|
||||
buffer[index] = 0;
|
||||
fprintf (stdout, "%s", buffer);
|
||||
_g_fprintf (stdout, "%s", buffer);
|
||||
state = 0;
|
||||
index = 0;
|
||||
}
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "glib.h"
|
||||
#include "gprintfint.h"
|
||||
|
||||
#ifdef G_PLATFORM_WIN32
|
||||
#define STRICT
|
||||
@ -338,7 +339,7 @@ open_converter (const gchar *to_codeset,
|
||||
|
||||
/* create our key */
|
||||
key = g_alloca (strlen (from_codeset) + strlen (to_codeset) + 2);
|
||||
sprintf (key, "%s:%s", from_codeset, to_codeset);
|
||||
_g_sprintf (key, "%s:%s", from_codeset, to_codeset);
|
||||
|
||||
G_LOCK (iconv_cache_lock);
|
||||
|
||||
|
354
glib/gmessages.c
354
glib/gmessages.c
@ -44,6 +44,7 @@
|
||||
#include <locale.h>
|
||||
#include <errno.h>
|
||||
#include "gdebug.h"
|
||||
#include "gprintfint.h"
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
typedef FILE* GFileDescriptor;
|
||||
@ -71,14 +72,6 @@ struct _GLogHandler
|
||||
};
|
||||
|
||||
|
||||
/* --- prototypes --- */
|
||||
#ifndef HAVE_C99_VSNPRINTF
|
||||
static gsize printf_string_upper_bound (const gchar *format,
|
||||
gboolean may_warn,
|
||||
va_list args);
|
||||
#endif /* !HAVE_C99_VSNPRINTF */
|
||||
|
||||
|
||||
/* --- variables --- */
|
||||
static GMutex *g_messages_lock = NULL;
|
||||
static GLogDomain *g_log_domains = NULL;
|
||||
@ -409,10 +402,6 @@ g_logv (const gchar *log_domain,
|
||||
gboolean was_recursion = (log_level & G_LOG_FLAG_RECURSION) != 0;
|
||||
gint i;
|
||||
|
||||
#ifndef HAVE_VSNPRINTF
|
||||
va_list args2;
|
||||
#endif /* HAVE_VSNPRINTF */
|
||||
|
||||
log_level &= G_LOG_LEVEL_MASK;
|
||||
if (!log_level)
|
||||
return;
|
||||
@ -420,21 +409,7 @@ g_logv (const gchar *log_domain,
|
||||
/* we use a stack buffer of fixed size, because we might get called
|
||||
* recursively.
|
||||
*/
|
||||
#ifdef HAVE_VSNPRINTF
|
||||
vsnprintf (buffer, 1024, format, args1);
|
||||
#else /* !HAVE_VSNPRINTF */
|
||||
G_VA_COPY (args2, args1);
|
||||
if (printf_string_upper_bound (format, FALSE, args1) < 1024)
|
||||
vsprintf (buffer, format, args2);
|
||||
else
|
||||
{
|
||||
/* since we might be out of memory, we can't use g_vsnprintf(). */
|
||||
/* we are out of luck here */
|
||||
strncpy (buffer, format, 1024);
|
||||
buffer[1024] = 0;
|
||||
}
|
||||
va_end (args2);
|
||||
#endif /* !HAVE_VSNPRINTF */
|
||||
_g_vsnprintf (buffer, 1024, format, args1);
|
||||
|
||||
for (i = g_bit_nth_msf (log_level, -1); i >= 0; i = g_bit_nth_msf (log_level, i))
|
||||
{
|
||||
@ -548,7 +523,7 @@ strdup_convert (const gchar *string,
|
||||
if (!warned)
|
||||
{
|
||||
warned = TRUE;
|
||||
fprintf (stderr, "GLib: Cannot convert message: %s\n", err->message);
|
||||
_g_fprintf (stderr, "GLib: Cannot convert message: %s\n", err->message);
|
||||
}
|
||||
g_error_free (err);
|
||||
|
||||
@ -909,333 +884,12 @@ g_printerr (const gchar *format,
|
||||
g_free (string);
|
||||
}
|
||||
|
||||
#ifndef MB_LEN_MAX
|
||||
# define MB_LEN_MAX 8
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_C99_VSNPRINTF
|
||||
|
||||
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 gsize
|
||||
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;
|
||||
gsize 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;
|
||||
gsize conv_len = 0;
|
||||
const gchar *spec_start = format;
|
||||
|
||||
do
|
||||
{
|
||||
c = *format++;
|
||||
switch (c)
|
||||
{
|
||||
GDoubleIEEE754 u_double;
|
||||
guint v_uint;
|
||||
gint v_int;
|
||||
const 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 */
|
||||
conv_done = TRUE;
|
||||
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)
|
||||
{
|
||||
(void) va_arg (args, 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 += ABS (exp); /* exp can be <0 */
|
||||
}
|
||||
/* 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;
|
||||
}
|
||||
|
||||
#endif /* !HAVE_C99_VSNPRINTF */
|
||||
|
||||
|
||||
gsize
|
||||
g_printf_string_upper_bound (const gchar *format,
|
||||
va_list args)
|
||||
{
|
||||
#if HAVE_C99_VSNPRINTF
|
||||
gchar c;
|
||||
return vsnprintf (&c, 1, format, args) + 1;
|
||||
#else
|
||||
return printf_string_upper_bound (format, TRUE, args);
|
||||
#endif
|
||||
return _g_vsnprintf (&c, 1, format, args) + 1;
|
||||
}
|
||||
|
||||
void
|
||||
|
253
glib/gprintf.c
Normal file
253
glib/gprintf.c
Normal file
@ -0,0 +1,253 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997, 2002 Peter Mattis, Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "glib.h"
|
||||
#include "gprintf.h"
|
||||
#include "gprintfint.h"
|
||||
|
||||
/**
|
||||
* g_printf:
|
||||
* @format: the format string. See the printf() documentation.
|
||||
* @Varargs: the arguments to insert in the output.
|
||||
*
|
||||
* An implementation of the standard printf() function which supports
|
||||
* positional parameters, as specified in the Single Unix Specification.
|
||||
*
|
||||
* Returns: the number of characters printed.
|
||||
**/
|
||||
gint
|
||||
g_printf (gchar const *fmt,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
gint retval;
|
||||
|
||||
va_start (args, fmt);
|
||||
retval = g_vprintf (fmt, args);
|
||||
va_end (args);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_fprintf:
|
||||
* @file: the stream to write to.
|
||||
* @format: the format string. See the printf() documentation.
|
||||
* @Varargs: the arguments to insert in the output.
|
||||
*
|
||||
* An implementation of the standard fprintf() function which supports
|
||||
* positional parameters, as specified in the Single Unix Specification.
|
||||
*
|
||||
* Returns: the number of characters printed.
|
||||
**/
|
||||
gint
|
||||
g_fprintf (FILE *file,
|
||||
gchar const *fmt,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
gint retval;
|
||||
|
||||
va_start (args, fmt);
|
||||
retval = g_vfprintf (file, fmt, args);
|
||||
va_end (args);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_sprintf:
|
||||
* @string: the buffer to hold the output.
|
||||
* @format: the format string. See the printf() documentation.
|
||||
* @Varargs: the arguments to insert in the output.
|
||||
*
|
||||
* An implementation of the standard sprintf() function which supports
|
||||
* positional parameters, as specified in the Single Unix Specification.
|
||||
*
|
||||
* Returns: the number of characters printed.
|
||||
**/
|
||||
gint
|
||||
g_sprintf (gchar *str,
|
||||
gchar const *fmt,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
gint retval;
|
||||
|
||||
va_start (args, fmt);
|
||||
retval = g_vsprintf (str, fmt, args);
|
||||
va_end (args);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_snprintf:
|
||||
* @string: the buffer to hold the output.
|
||||
* @n: the maximum number of characters to produce (including the
|
||||
* terminating nul character).
|
||||
* @format: the format string. See the printf() documentation.
|
||||
* @Varargs: the arguments to insert in the output.
|
||||
*
|
||||
* A safer form of the standard sprintf() function. The output is guaranteed
|
||||
* to not exceed @n characters (including the terminating nul character), so
|
||||
* it is easy to ensure that a buffer overflow cannot occur.
|
||||
*
|
||||
* See also g_strdup_printf().
|
||||
*
|
||||
* In versions of GLib prior to 1.2.3, this function may return -1 if the
|
||||
* output was truncated, and the truncated string may not be nul-terminated.
|
||||
* In versions prior to 1.3.12, this function returns the length of the output
|
||||
* string.
|
||||
*
|
||||
* The return value of g_snprintf() conforms to the snprintf()
|
||||
* function as standardized in ISO C99. Note that this is different from
|
||||
* traditional snprintf(), which returns the length of the output string.
|
||||
*
|
||||
* The format string may contain positional parameters, as specified in
|
||||
* the Single Unix Specification.
|
||||
*
|
||||
* Returns: the number of characters which would be produced if the buffer
|
||||
* was large enough.
|
||||
**/
|
||||
gint
|
||||
g_snprintf (gchar *str,
|
||||
gulong n,
|
||||
gchar const *fmt,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
gint retval;
|
||||
|
||||
va_start (args, fmt);
|
||||
retval = g_vsnprintf (str, n, fmt, args);
|
||||
va_end (args);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_vprintf:
|
||||
* @format: the format string. See the printf() documentation.
|
||||
* @args: the list of arguments to insert in the output.
|
||||
*
|
||||
* An implementation of the standard vprintf() function which supports
|
||||
* positional parameters, as specified in the Single Unix Specification.
|
||||
*
|
||||
* Returns: the number of characters printed.
|
||||
**/
|
||||
gint
|
||||
g_vprintf (gchar const *fmt,
|
||||
va_list args)
|
||||
{
|
||||
g_return_val_if_fail (fmt != NULL, 0);
|
||||
|
||||
return _g_vprintf (fmt, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_vfprintf:
|
||||
* @file: the stream to write to.
|
||||
* @format: the format string. See the printf() documentation.
|
||||
* @args: the list of arguments to insert in the output.
|
||||
*
|
||||
* An implementation of the standard fprintf() function which supports
|
||||
* positional parameters, as specified in the Single Unix Specification.
|
||||
*
|
||||
* Returns: the number of characters printed.
|
||||
**/
|
||||
gint
|
||||
g_vfprintf (FILE *file,
|
||||
gchar const *fmt,
|
||||
va_list args)
|
||||
{
|
||||
g_return_val_if_fail (fmt != NULL, 0);
|
||||
|
||||
return _g_vfprintf (file, fmt, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_vsprintf:
|
||||
* @string: the buffer to hold the output.
|
||||
* @format: the format string. See the printf() documentation.
|
||||
* @args: the list of arguments to insert in the output.
|
||||
*
|
||||
* An implementation of the standard vsprintf() function which supports
|
||||
* positional parameters, as specified in the Single Unix Specification.
|
||||
*
|
||||
* Returns: the number of characters printed.
|
||||
**/
|
||||
gint
|
||||
g_vsprintf (gchar *str,
|
||||
gchar const *fmt,
|
||||
va_list args)
|
||||
{
|
||||
g_return_val_if_fail (str != NULL, 0);
|
||||
g_return_val_if_fail (fmt != NULL, 0);
|
||||
|
||||
return _g_vsprintf (str, fmt, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_vsnprintf:
|
||||
* @string: the buffer to hold the output.
|
||||
* @n: the maximum number of characters to produce (including the
|
||||
* terminating nul character).
|
||||
* @format: the format string. See the printf() documentation.
|
||||
* @args: the list of arguments to insert in the output.
|
||||
*
|
||||
* A safer form of the standard vsprintf() function. The output is guaranteed
|
||||
* to not exceed @n characters (including the terminating nul character), so
|
||||
* it is easy to ensure that a buffer overflow cannot occur.
|
||||
*
|
||||
* See also g_strdup_vprintf().
|
||||
*
|
||||
* In versions of GLib prior to 1.2.3, this function may return -1 if the
|
||||
* output was truncated, and the truncated string may not be nul-terminated.
|
||||
* In versions prior to 1.3.12, this function returns the length of the output
|
||||
* string.
|
||||
*
|
||||
* The return value of g_vsnprintf() conforms to the vsnprintf() function
|
||||
* as standardized in ISO C99. Note that this is different from traditional
|
||||
* vsnprintf(), which returns the length of the output string.
|
||||
*
|
||||
* The format string may contain positional parameters, as specified in
|
||||
* the Single Unix Specification.
|
||||
*
|
||||
* Returns: the number of characters which would be produced if the buffer
|
||||
* was large enough.
|
||||
*/
|
||||
gint
|
||||
g_vsnprintf (gchar *str,
|
||||
gulong n,
|
||||
gchar const *fmt,
|
||||
va_list args)
|
||||
{
|
||||
g_return_val_if_fail (n == 0 || str != NULL, 0);
|
||||
g_return_val_if_fail (fmt != NULL, 0);
|
||||
|
||||
return _g_vsnprintf (str, n, fmt, args);
|
||||
}
|
||||
|
||||
|
||||
|
60
glib/gprintf.h
Normal file
60
glib/gprintf.h
Normal file
@ -0,0 +1,60 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997, 2002 Peter Mattis, Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __G_PRINTF_H__
|
||||
#define __G_PRINTF_H__
|
||||
|
||||
#include <glib/gtypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
gint g_printf (gchar const *format,
|
||||
...) G_GNUC_PRINTF (1, 2);
|
||||
gint g_fprintf (FILE *file,
|
||||
gchar const *format,
|
||||
...) G_GNUC_PRINTF (2, 3);
|
||||
gint g_sprintf (gchar *string,
|
||||
gchar const *format,
|
||||
...) G_GNUC_PRINTF (2, 3);
|
||||
gint g_snprintf (gchar *string,
|
||||
gulong n,
|
||||
gchar const *format,
|
||||
...) G_GNUC_PRINTF (3, 4);
|
||||
|
||||
gint g_vprintf (gchar const *format,
|
||||
va_list args);
|
||||
gint g_vfprintf (FILE *file,
|
||||
gchar const *format,
|
||||
va_list args);
|
||||
gint g_vsprintf (gchar *string,
|
||||
gchar const *format,
|
||||
va_list args);
|
||||
gint g_vsnprintf (gchar *string,
|
||||
gulong n,
|
||||
gchar const *format,
|
||||
va_list args);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_PRINTF_H__ */
|
||||
|
||||
|
||||
|
63
glib/gprintfint.h
Normal file
63
glib/gprintfint.h
Normal file
@ -0,0 +1,63 @@
|
||||
/* GLIB - Library of useful routines for C programming
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GLib Team and others 2002. See the AUTHORS
|
||||
* file for a list of people on the GLib Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GLib at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#ifndef __G_PRINTFINT_H__
|
||||
#define __G_PRINTFINT_H__
|
||||
|
||||
#ifdef HAVE_GOOD_PRINTF
|
||||
|
||||
#define _g_printf printf
|
||||
#define _g_fprintf fprintf
|
||||
#define _g_sprintf sprintf
|
||||
#define _g_snprintf snprintf
|
||||
|
||||
#define _g_vprintf vprintf
|
||||
#define _g_vfprintf vfprintf
|
||||
#define _g_vsprintf vsprintf
|
||||
#define _g_vsnprintf vsnprintf
|
||||
|
||||
#define _g_vasprintf vasprintf
|
||||
|
||||
#else
|
||||
|
||||
#include "trio/trio.h"
|
||||
|
||||
#define _g_printf trio_printf
|
||||
#define _g_fprintf trio_fprintf
|
||||
#define _g_sprintf trio_sprintf
|
||||
#define _g_snprintf trio_snprintf
|
||||
|
||||
#define _g_vprintf trio_vprintf
|
||||
#define _g_vfprintf trio_vfprintf
|
||||
#define _g_vsprintf trio_vsprintf
|
||||
#define _g_vsnprintf trio_vsnprintf
|
||||
|
||||
#define _g_vasprintf trio_vasprintf
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __G_PRINTF_H__ */
|
||||
|
149
glib/gscanner.c
149
glib/gscanner.c
@ -40,6 +40,7 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "glib.h"
|
||||
#include "gprintfint.h"
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
@ -290,12 +291,12 @@ g_scanner_msg_handler (GScanner *scanner,
|
||||
{
|
||||
g_return_if_fail (scanner != NULL);
|
||||
|
||||
fprintf (stderr, "%s:%d: ",
|
||||
scanner->input_name ? scanner->input_name : "<memory>",
|
||||
scanner->line);
|
||||
_g_fprintf (stderr, "%s:%d: ",
|
||||
scanner->input_name ? scanner->input_name : "<memory>",
|
||||
scanner->line);
|
||||
if (is_error)
|
||||
fprintf (stderr, "error: ");
|
||||
fprintf (stderr, "%s\n", message);
|
||||
_g_fprintf (stderr, "error: ");
|
||||
_g_fprintf (stderr, "%s\n", message);
|
||||
}
|
||||
|
||||
void
|
||||
@ -856,7 +857,7 @@ g_scanner_unexp_token (GScanner *scanner,
|
||||
switch (scanner->token)
|
||||
{
|
||||
case G_TOKEN_EOF:
|
||||
g_snprintf (token_string, token_string_len, "end of file");
|
||||
_g_snprintf (token_string, token_string_len, "end of file");
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -865,14 +866,14 @@ g_scanner_unexp_token (GScanner *scanner,
|
||||
if ((scanner->token >= ' ' && scanner->token <= '~') ||
|
||||
strchr (scanner->config->cset_identifier_first, scanner->token) ||
|
||||
strchr (scanner->config->cset_identifier_nth, scanner->token))
|
||||
g_snprintf (token_string, token_string_len, "character `%c'", scanner->token);
|
||||
_g_snprintf (token_string, token_string_len, "character `%c'", scanner->token);
|
||||
else
|
||||
g_snprintf (token_string, token_string_len, "character `\\%o'", scanner->token);
|
||||
_g_snprintf (token_string, token_string_len, "character `\\%o'", scanner->token);
|
||||
break;
|
||||
}
|
||||
else if (!scanner->config->symbol_2_token)
|
||||
{
|
||||
g_snprintf (token_string, token_string_len, "(unknown) token <%d>", scanner->token);
|
||||
_g_snprintf (token_string, token_string_len, "(unknown) token <%d>", scanner->token);
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
@ -882,18 +883,18 @@ g_scanner_unexp_token (GScanner *scanner,
|
||||
expected_token > G_TOKEN_LAST))
|
||||
print_unexp = FALSE;
|
||||
if (symbol_name)
|
||||
g_snprintf (token_string,
|
||||
token_string_len,
|
||||
"%s%s `%s'",
|
||||
print_unexp ? "" : "invalid ",
|
||||
symbol_spec,
|
||||
symbol_name);
|
||||
_g_snprintf (token_string,
|
||||
token_string_len,
|
||||
"%s%s `%s'",
|
||||
print_unexp ? "" : "invalid ",
|
||||
symbol_spec,
|
||||
symbol_name);
|
||||
else
|
||||
g_snprintf (token_string,
|
||||
token_string_len,
|
||||
"%s%s",
|
||||
print_unexp ? "" : "invalid ",
|
||||
symbol_spec);
|
||||
_g_snprintf (token_string,
|
||||
token_string_len,
|
||||
"%s%s",
|
||||
print_unexp ? "" : "invalid ",
|
||||
symbol_spec);
|
||||
break;
|
||||
|
||||
case G_TOKEN_ERROR:
|
||||
@ -902,42 +903,42 @@ g_scanner_unexp_token (GScanner *scanner,
|
||||
switch (scanner->value.v_error)
|
||||
{
|
||||
case G_ERR_UNEXP_EOF:
|
||||
g_snprintf (token_string, token_string_len, "scanner: unexpected end of file");
|
||||
_g_snprintf (token_string, token_string_len, "scanner: unexpected end of file");
|
||||
break;
|
||||
|
||||
case G_ERR_UNEXP_EOF_IN_STRING:
|
||||
g_snprintf (token_string, token_string_len, "scanner: unterminated string constant");
|
||||
_g_snprintf (token_string, token_string_len, "scanner: unterminated string constant");
|
||||
break;
|
||||
|
||||
case G_ERR_UNEXP_EOF_IN_COMMENT:
|
||||
g_snprintf (token_string, token_string_len, "scanner: unterminated comment");
|
||||
_g_snprintf (token_string, token_string_len, "scanner: unterminated comment");
|
||||
break;
|
||||
|
||||
case G_ERR_NON_DIGIT_IN_CONST:
|
||||
g_snprintf (token_string, token_string_len, "scanner: non digit in constant");
|
||||
_g_snprintf (token_string, token_string_len, "scanner: non digit in constant");
|
||||
break;
|
||||
|
||||
case G_ERR_FLOAT_RADIX:
|
||||
g_snprintf (token_string, token_string_len, "scanner: invalid radix for floating constant");
|
||||
_g_snprintf (token_string, token_string_len, "scanner: invalid radix for floating constant");
|
||||
break;
|
||||
|
||||
case G_ERR_FLOAT_MALFORMED:
|
||||
g_snprintf (token_string, token_string_len, "scanner: malformed floating constant");
|
||||
_g_snprintf (token_string, token_string_len, "scanner: malformed floating constant");
|
||||
break;
|
||||
|
||||
case G_ERR_DIGIT_RADIX:
|
||||
g_snprintf (token_string, token_string_len, "scanner: digit is beyond radix");
|
||||
_g_snprintf (token_string, token_string_len, "scanner: digit is beyond radix");
|
||||
break;
|
||||
|
||||
case G_ERR_UNKNOWN:
|
||||
default:
|
||||
g_snprintf (token_string, token_string_len, "scanner: unknown error");
|
||||
_g_snprintf (token_string, token_string_len, "scanner: unknown error");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case G_TOKEN_CHAR:
|
||||
g_snprintf (token_string, token_string_len, "character `%c'", scanner->value.v_char);
|
||||
_g_snprintf (token_string, token_string_len, "character `%c'", scanner->value.v_char);
|
||||
break;
|
||||
|
||||
case G_TOKEN_IDENTIFIER:
|
||||
@ -945,7 +946,7 @@ g_scanner_unexp_token (GScanner *scanner,
|
||||
if (expected_token == G_TOKEN_IDENTIFIER ||
|
||||
expected_token == G_TOKEN_IDENTIFIER_NULL)
|
||||
print_unexp = FALSE;
|
||||
g_snprintf (token_string,
|
||||
_g_snprintf (token_string,
|
||||
token_string_len,
|
||||
"%s%s `%s'",
|
||||
print_unexp ? "" : "invalid ",
|
||||
@ -958,31 +959,31 @@ g_scanner_unexp_token (GScanner *scanner,
|
||||
case G_TOKEN_INT:
|
||||
case G_TOKEN_HEX:
|
||||
if (scanner->config->store_int64)
|
||||
g_snprintf (token_string, token_string_len, "number `%llu'", scanner->value.v_int64);
|
||||
_g_snprintf (token_string, token_string_len, "number `%llu'", scanner->value.v_int64);
|
||||
else
|
||||
g_snprintf (token_string, token_string_len, "number `%lu'", scanner->value.v_int);
|
||||
_g_snprintf (token_string, token_string_len, "number `%lu'", scanner->value.v_int);
|
||||
break;
|
||||
|
||||
case G_TOKEN_FLOAT:
|
||||
g_snprintf (token_string, token_string_len, "number `%.3f'", scanner->value.v_float);
|
||||
_g_snprintf (token_string, token_string_len, "number `%.3f'", scanner->value.v_float);
|
||||
break;
|
||||
|
||||
case G_TOKEN_STRING:
|
||||
if (expected_token == G_TOKEN_STRING)
|
||||
print_unexp = FALSE;
|
||||
g_snprintf (token_string,
|
||||
token_string_len,
|
||||
"%s%sstring constant \"%s\"",
|
||||
print_unexp ? "" : "invalid ",
|
||||
scanner->value.v_string[0] == 0 ? "empty " : "",
|
||||
scanner->value.v_string);
|
||||
_g_snprintf (token_string,
|
||||
token_string_len,
|
||||
"%s%sstring constant \"%s\"",
|
||||
print_unexp ? "" : "invalid ",
|
||||
scanner->value.v_string[0] == 0 ? "empty " : "",
|
||||
scanner->value.v_string);
|
||||
token_string[token_string_len - 2] = '"';
|
||||
token_string[token_string_len - 1] = 0;
|
||||
break;
|
||||
|
||||
case G_TOKEN_COMMENT_SINGLE:
|
||||
case G_TOKEN_COMMENT_MULTI:
|
||||
g_snprintf (token_string, token_string_len, "comment");
|
||||
_g_snprintf (token_string, token_string_len, "comment");
|
||||
break;
|
||||
|
||||
case G_TOKEN_NONE:
|
||||
@ -1002,7 +1003,7 @@ g_scanner_unexp_token (GScanner *scanner,
|
||||
gboolean need_valid;
|
||||
gchar *tstring;
|
||||
case G_TOKEN_EOF:
|
||||
g_snprintf (expected_string, expected_string_len, "end of file");
|
||||
_g_snprintf (expected_string, expected_string_len, "end of file");
|
||||
break;
|
||||
default:
|
||||
if (expected_token >= 1 && expected_token <= 255)
|
||||
@ -1010,14 +1011,14 @@ g_scanner_unexp_token (GScanner *scanner,
|
||||
if ((expected_token >= ' ' && expected_token <= '~') ||
|
||||
strchr (scanner->config->cset_identifier_first, expected_token) ||
|
||||
strchr (scanner->config->cset_identifier_nth, expected_token))
|
||||
g_snprintf (expected_string, expected_string_len, "character `%c'", expected_token);
|
||||
_g_snprintf (expected_string, expected_string_len, "character `%c'", expected_token);
|
||||
else
|
||||
g_snprintf (expected_string, expected_string_len, "character `\\%o'", expected_token);
|
||||
_g_snprintf (expected_string, expected_string_len, "character `\\%o'", expected_token);
|
||||
break;
|
||||
}
|
||||
else if (!scanner->config->symbol_2_token)
|
||||
{
|
||||
g_snprintf (expected_string, expected_string_len, "(unknown) token <%d>", expected_token);
|
||||
_g_snprintf (expected_string, expected_string_len, "(unknown) token <%d>", expected_token);
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
@ -1025,67 +1026,67 @@ g_scanner_unexp_token (GScanner *scanner,
|
||||
need_valid = (scanner->token == G_TOKEN_SYMBOL ||
|
||||
(scanner->config->symbol_2_token &&
|
||||
scanner->token > G_TOKEN_LAST));
|
||||
g_snprintf (expected_string,
|
||||
expected_string_len,
|
||||
"%s%s",
|
||||
need_valid ? "valid " : "",
|
||||
symbol_spec);
|
||||
_g_snprintf (expected_string,
|
||||
expected_string_len,
|
||||
"%s%s",
|
||||
need_valid ? "valid " : "",
|
||||
symbol_spec);
|
||||
/* FIXME: should we attempt to lookup the symbol_name for symbol_2_token? */
|
||||
break;
|
||||
case G_TOKEN_CHAR:
|
||||
g_snprintf (expected_string, expected_string_len, "%scharacter",
|
||||
scanner->token == G_TOKEN_CHAR ? "valid " : "");
|
||||
_g_snprintf (expected_string, expected_string_len, "%scharacter",
|
||||
scanner->token == G_TOKEN_CHAR ? "valid " : "");
|
||||
break;
|
||||
case G_TOKEN_BINARY:
|
||||
tstring = "binary";
|
||||
g_snprintf (expected_string, expected_string_len, "%snumber (%s)",
|
||||
scanner->token == expected_token ? "valid " : "", tstring);
|
||||
_g_snprintf (expected_string, expected_string_len, "%snumber (%s)",
|
||||
scanner->token == expected_token ? "valid " : "", tstring);
|
||||
break;
|
||||
case G_TOKEN_OCTAL:
|
||||
tstring = "octal";
|
||||
g_snprintf (expected_string, expected_string_len, "%snumber (%s)",
|
||||
scanner->token == expected_token ? "valid " : "", tstring);
|
||||
_g_snprintf (expected_string, expected_string_len, "%snumber (%s)",
|
||||
scanner->token == expected_token ? "valid " : "", tstring);
|
||||
break;
|
||||
case G_TOKEN_INT:
|
||||
tstring = "integer";
|
||||
g_snprintf (expected_string, expected_string_len, "%snumber (%s)",
|
||||
scanner->token == expected_token ? "valid " : "", tstring);
|
||||
_g_snprintf (expected_string, expected_string_len, "%snumber (%s)",
|
||||
scanner->token == expected_token ? "valid " : "", tstring);
|
||||
break;
|
||||
case G_TOKEN_HEX:
|
||||
tstring = "hexadecimal";
|
||||
g_snprintf (expected_string, expected_string_len, "%snumber (%s)",
|
||||
scanner->token == expected_token ? "valid " : "", tstring);
|
||||
_g_snprintf (expected_string, expected_string_len, "%snumber (%s)",
|
||||
scanner->token == expected_token ? "valid " : "", tstring);
|
||||
break;
|
||||
case G_TOKEN_FLOAT:
|
||||
tstring = "float";
|
||||
g_snprintf (expected_string, expected_string_len, "%snumber (%s)",
|
||||
scanner->token == expected_token ? "valid " : "", tstring);
|
||||
_g_snprintf (expected_string, expected_string_len, "%snumber (%s)",
|
||||
scanner->token == expected_token ? "valid " : "", tstring);
|
||||
break;
|
||||
case G_TOKEN_STRING:
|
||||
g_snprintf (expected_string,
|
||||
expected_string_len,
|
||||
"%sstring constant",
|
||||
scanner->token == G_TOKEN_STRING ? "valid " : "");
|
||||
_g_snprintf (expected_string,
|
||||
expected_string_len,
|
||||
"%sstring constant",
|
||||
scanner->token == G_TOKEN_STRING ? "valid " : "");
|
||||
break;
|
||||
case G_TOKEN_IDENTIFIER:
|
||||
case G_TOKEN_IDENTIFIER_NULL:
|
||||
need_valid = (scanner->token == G_TOKEN_IDENTIFIER_NULL ||
|
||||
scanner->token == G_TOKEN_IDENTIFIER);
|
||||
g_snprintf (expected_string,
|
||||
expected_string_len,
|
||||
"%s%s",
|
||||
need_valid ? "valid " : "",
|
||||
identifier_spec);
|
||||
_g_snprintf (expected_string,
|
||||
expected_string_len,
|
||||
"%s%s",
|
||||
need_valid ? "valid " : "",
|
||||
identifier_spec);
|
||||
break;
|
||||
case G_TOKEN_COMMENT_SINGLE:
|
||||
tstring = "single-line";
|
||||
g_snprintf (expected_string, expected_string_len, "%scomment (%s)",
|
||||
scanner->token == expected_token ? "valid " : "", tstring);
|
||||
_g_snprintf (expected_string, expected_string_len, "%scomment (%s)",
|
||||
scanner->token == expected_token ? "valid " : "", tstring);
|
||||
break;
|
||||
case G_TOKEN_COMMENT_MULTI:
|
||||
tstring = "multi-line";
|
||||
g_snprintf (expected_string, expected_string_len, "%scomment (%s)",
|
||||
scanner->token == expected_token ? "valid " : "", tstring);
|
||||
_g_snprintf (expected_string, expected_string_len, "%scomment (%s)",
|
||||
scanner->token == expected_token ? "valid " : "", tstring);
|
||||
break;
|
||||
case G_TOKEN_NONE:
|
||||
case G_TOKEN_ERROR:
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include <config.h>
|
||||
|
||||
#include "glib.h"
|
||||
#include "gprintfint.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@ -555,12 +556,12 @@ do_spawn (gboolean dont_wait,
|
||||
new_argv = g_new (gchar *, argc + 1 + ARG_COUNT);
|
||||
|
||||
new_argv[0] = "gspawn-win32-helper";
|
||||
sprintf (args[ARG_CHILD_ERR_REPORT], "%d", child_err_report_fd);
|
||||
_g_sprintf (args[ARG_CHILD_ERR_REPORT], "%d", child_err_report_fd);
|
||||
new_argv[ARG_CHILD_ERR_REPORT] = args[ARG_CHILD_ERR_REPORT];
|
||||
|
||||
if (stdin_fd >= 0)
|
||||
{
|
||||
sprintf (args[ARG_STDIN], "%d", stdin_fd);
|
||||
_g_sprintf (args[ARG_STDIN], "%d", stdin_fd);
|
||||
new_argv[ARG_STDIN] = args[ARG_STDIN];
|
||||
}
|
||||
else if (child_inherits_stdin)
|
||||
@ -576,7 +577,7 @@ do_spawn (gboolean dont_wait,
|
||||
|
||||
if (stdout_fd >= 0)
|
||||
{
|
||||
sprintf (args[ARG_STDOUT], "%d", stdout_fd);
|
||||
_g_sprintf (args[ARG_STDOUT], "%d", stdout_fd);
|
||||
new_argv[ARG_STDOUT] = args[ARG_STDOUT];
|
||||
}
|
||||
else if (stdout_to_null)
|
||||
@ -590,7 +591,7 @@ do_spawn (gboolean dont_wait,
|
||||
|
||||
if (stderr_fd >= 0)
|
||||
{
|
||||
sprintf (args[ARG_STDERR], "%d", stderr_fd);
|
||||
_g_sprintf (args[ARG_STDERR], "%d", stderr_fd);
|
||||
new_argv[ARG_STDERR] = args[ARG_STDERR];
|
||||
}
|
||||
else if (stderr_to_null)
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include <signal.h>
|
||||
#endif
|
||||
#include "glib.h"
|
||||
#include "gprintfint.h"
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
#include <windows.h>
|
||||
@ -183,7 +184,7 @@ g_strdup_vprintf (const gchar *format,
|
||||
{
|
||||
gchar *buffer;
|
||||
#ifdef HAVE_VASPRINTF
|
||||
if (vasprintf (&buffer, format, args1) < 0)
|
||||
if (_g_vasprintf (&buffer, format, args1) < 0)
|
||||
buffer = NULL;
|
||||
else if (!g_mem_is_system_malloc ())
|
||||
{
|
||||
@ -198,7 +199,7 @@ g_strdup_vprintf (const gchar *format,
|
||||
|
||||
buffer = g_new (gchar, g_printf_string_upper_bound (format, args1));
|
||||
|
||||
vsprintf (buffer, format, args2);
|
||||
_g_vsprintf (buffer, format, args2);
|
||||
va_end (args2);
|
||||
#endif
|
||||
return buffer;
|
||||
@ -544,7 +545,7 @@ g_ascii_formatd (gchar *buffer,
|
||||
return NULL;
|
||||
|
||||
|
||||
g_snprintf (buffer, buf_len, format, d);
|
||||
_g_snprintf (buffer, buf_len, format, d);
|
||||
|
||||
locale_data = localeconv ();
|
||||
decimal_point = locale_data->decimal_point;
|
||||
@ -1187,7 +1188,7 @@ g_strerror (gint errnum)
|
||||
g_static_private_set (&msg_private, msg, g_free);
|
||||
}
|
||||
|
||||
sprintf (msg, "unknown error (%d)", errnum);
|
||||
_g_sprintf (msg, "unknown error (%d)", errnum);
|
||||
|
||||
return msg;
|
||||
}
|
||||
@ -1336,7 +1337,7 @@ extern const char *strsignal(int);
|
||||
g_static_private_set (&msg_private, msg, g_free);
|
||||
}
|
||||
|
||||
sprintf (msg, "unknown signal (%d)", signum);
|
||||
_g_sprintf (msg, "unknown signal (%d)", signum);
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
@ -53,6 +53,7 @@
|
||||
#define G_IMPLEMENT_INLINES 1
|
||||
#define __G_UTILS_C__
|
||||
#include "glib.h"
|
||||
#include "gprintfint.h"
|
||||
|
||||
#ifdef MAXPATHLEN
|
||||
#define G_PATH_LENGTH MAXPATHLEN
|
||||
@ -340,54 +341,6 @@ g_find_program_in_path (const gchar *program)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gint
|
||||
g_snprintf (gchar *str,
|
||||
gulong n,
|
||||
gchar const *fmt,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
gint retval;
|
||||
|
||||
va_start (args, fmt);
|
||||
retval = g_vsnprintf (str, n, fmt, args);
|
||||
va_end (args);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
gint
|
||||
g_vsnprintf (gchar *str,
|
||||
gulong n,
|
||||
gchar const *fmt,
|
||||
va_list args)
|
||||
{
|
||||
#ifdef HAVE_VSNPRINTF_C99
|
||||
g_return_val_if_fail (n == 0 || str != NULL, 0);
|
||||
g_return_val_if_fail (fmt != NULL, 0);
|
||||
|
||||
return vsnprintf (str, n, fmt, args);
|
||||
#else /* !HAVE_VSNPRINTF_C99 */
|
||||
gchar *printed;
|
||||
gint retval;
|
||||
|
||||
g_return_val_if_fail (n == 0 || str != NULL, 0);
|
||||
g_return_val_if_fail (fmt != NULL, 0);
|
||||
|
||||
printed = g_strdup_vprintf (fmt, args);
|
||||
retval = strlen (printed);
|
||||
if (n > 0)
|
||||
{
|
||||
strncpy (str, printed, n - 1);
|
||||
str[n-1] = '\0';
|
||||
}
|
||||
|
||||
g_free (printed);
|
||||
|
||||
return retval;
|
||||
#endif /* !HAVE_VSNPRINTF_C99 */
|
||||
}
|
||||
|
||||
guint
|
||||
g_parse_debug_string (const gchar *string,
|
||||
const GDebugKey *keys,
|
||||
|
17
glib/trio/Makefile.am
Normal file
17
glib/trio/Makefile.am
Normal file
@ -0,0 +1,17 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
noinst_LTLIBRARIES = libtrio.la
|
||||
|
||||
libtrio_la_SOURCES = \
|
||||
trio.c \
|
||||
trionan.c \
|
||||
triostr.c \
|
||||
trio.h \
|
||||
triodef.h \
|
||||
trionan.h \
|
||||
triop.h \
|
||||
triostr.h
|
||||
|
||||
INCLUDES = -DTRIO_EXTENSION=0
|
||||
|
||||
EXTRA_DIST = README
|
27
glib/trio/README
Normal file
27
glib/trio/README
Normal file
@ -0,0 +1,27 @@
|
||||
The sources are derived from the trio package, version 1.9, by
|
||||
Bjorn Reese and Daniel Stenberg, which can be found at:
|
||||
|
||||
http://daniel.haxx.se/trio/
|
||||
http://sourceforge.net/projects/ctrio/
|
||||
|
||||
The license on the files taken from the trio package is reproduced
|
||||
below.
|
||||
|
||||
Matthias Clasen
|
||||
20 November 2002
|
||||
|
||||
====
|
||||
|
||||
Copyright (C) 1998-2001 by Bjorn Reese and Daniel Stenberg.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
|
||||
CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
|
||||
|
||||
|
||||
|
6760
glib/trio/trio.c
Normal file
6760
glib/trio/trio.c
Normal file
File diff suppressed because it is too large
Load Diff
216
glib/trio/trio.h
Normal file
216
glib/trio/trio.h
Normal file
@ -0,0 +1,216 @@
|
||||
/*************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 1998 Bjorn Reese and Daniel Stenberg.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
|
||||
* CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
|
||||
*
|
||||
*************************************************************************
|
||||
*
|
||||
* http://ctrio.sourceforge.net/
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
#ifndef TRIO_TRIO_H
|
||||
#define TRIO_TRIO_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#if defined(TRIO_COMPILER_ANCIENT)
|
||||
# include <varargs.h>
|
||||
#else
|
||||
# include <stdarg.h>
|
||||
#endif
|
||||
|
||||
#if !defined(WITHOUT_TRIO)
|
||||
|
||||
/*
|
||||
* Use autoconf defines if present. Packages using trio must define
|
||||
* HAVE_CONFIG_H as a compiler option themselves.
|
||||
*/
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "triodef.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Error codes.
|
||||
*
|
||||
* Remember to add a textual description to trio_strerror.
|
||||
*/
|
||||
enum {
|
||||
TRIO_EOF = 1,
|
||||
TRIO_EINVAL = 2,
|
||||
TRIO_ETOOMANY = 3,
|
||||
TRIO_EDBLREF = 4,
|
||||
TRIO_EGAP = 5,
|
||||
TRIO_ENOMEM = 6,
|
||||
TRIO_ERANGE = 7,
|
||||
TRIO_ERRNO = 8,
|
||||
TRIO_ECUSTOM = 9
|
||||
};
|
||||
|
||||
/* Error macros */
|
||||
#define TRIO_ERROR_CODE(x) ((-(x)) & 0x00FF)
|
||||
#define TRIO_ERROR_POSITION(x) ((-(x)) >> 8)
|
||||
#define TRIO_ERROR_NAME(x) trio_strerror(x)
|
||||
|
||||
typedef int (*trio_outstream_t) TRIO_PROTO((trio_pointer_t, int));
|
||||
typedef int (*trio_instream_t) TRIO_PROTO((trio_pointer_t));
|
||||
|
||||
TRIO_CONST char *trio_strerror TRIO_PROTO((int));
|
||||
|
||||
/*************************************************************************
|
||||
* Print Functions
|
||||
*/
|
||||
|
||||
int trio_printf TRIO_PROTO((TRIO_CONST char *format, ...));
|
||||
int trio_vprintf TRIO_PROTO((TRIO_CONST char *format, va_list args));
|
||||
int trio_printfv TRIO_PROTO((TRIO_CONST char *format, void **args));
|
||||
|
||||
int trio_fprintf TRIO_PROTO((FILE *file, TRIO_CONST char *format, ...));
|
||||
int trio_vfprintf TRIO_PROTO((FILE *file, TRIO_CONST char *format, va_list args));
|
||||
int trio_fprintfv TRIO_PROTO((FILE *file, TRIO_CONST char *format, void **args));
|
||||
|
||||
int trio_dprintf TRIO_PROTO((int fd, TRIO_CONST char *format, ...));
|
||||
int trio_vdprintf TRIO_PROTO((int fd, TRIO_CONST char *format, va_list args));
|
||||
int trio_dprintfv TRIO_PROTO((int fd, TRIO_CONST char *format, void **args));
|
||||
|
||||
int trio_cprintf TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure,
|
||||
TRIO_CONST char *format, ...));
|
||||
int trio_vcprintf TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure,
|
||||
TRIO_CONST char *format, va_list args));
|
||||
int trio_cprintfv TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure,
|
||||
TRIO_CONST char *format, void **args));
|
||||
|
||||
int trio_sprintf TRIO_PROTO((char *buffer, TRIO_CONST char *format, ...));
|
||||
int trio_vsprintf TRIO_PROTO((char *buffer, TRIO_CONST char *format, va_list args));
|
||||
int trio_sprintfv TRIO_PROTO((char *buffer, TRIO_CONST char *format, void **args));
|
||||
|
||||
int trio_snprintf TRIO_PROTO((char *buffer, size_t max, TRIO_CONST char *format, ...));
|
||||
int trio_vsnprintf TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format,
|
||||
va_list args));
|
||||
int trio_snprintfv TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format,
|
||||
void **args));
|
||||
|
||||
int trio_snprintfcat TRIO_PROTO((char *buffer, size_t max, TRIO_CONST char *format, ...));
|
||||
int trio_vsnprintfcat TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format,
|
||||
va_list args));
|
||||
|
||||
char *trio_aprintf TRIO_PROTO((TRIO_CONST char *format, ...));
|
||||
char *trio_vaprintf TRIO_PROTO((TRIO_CONST char *format, va_list args));
|
||||
|
||||
int trio_asprintf TRIO_PROTO((char **ret, TRIO_CONST char *format, ...));
|
||||
int trio_vasprintf TRIO_PROTO((char **ret, TRIO_CONST char *format, va_list args));
|
||||
|
||||
/*************************************************************************
|
||||
* Scan Functions
|
||||
*/
|
||||
int trio_scanf TRIO_PROTO((TRIO_CONST char *format, ...));
|
||||
int trio_vscanf TRIO_PROTO((TRIO_CONST char *format, va_list args));
|
||||
int trio_scanfv TRIO_PROTO((TRIO_CONST char *format, void **args));
|
||||
|
||||
int trio_fscanf TRIO_PROTO((FILE *file, TRIO_CONST char *format, ...));
|
||||
int trio_vfscanf TRIO_PROTO((FILE *file, TRIO_CONST char *format, va_list args));
|
||||
int trio_fscanfv TRIO_PROTO((FILE *file, TRIO_CONST char *format, void **args));
|
||||
|
||||
int trio_dscanf TRIO_PROTO((int fd, TRIO_CONST char *format, ...));
|
||||
int trio_vdscanf TRIO_PROTO((int fd, TRIO_CONST char *format, va_list args));
|
||||
int trio_dscanfv TRIO_PROTO((int fd, TRIO_CONST char *format, void **args));
|
||||
|
||||
int trio_cscanf TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure,
|
||||
TRIO_CONST char *format, ...));
|
||||
int trio_vcscanf TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure,
|
||||
TRIO_CONST char *format, va_list args));
|
||||
int trio_cscanfv TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure,
|
||||
TRIO_CONST char *format, void **args));
|
||||
|
||||
int trio_sscanf TRIO_PROTO((TRIO_CONST char *buffer, TRIO_CONST char *format, ...));
|
||||
int trio_vsscanf TRIO_PROTO((TRIO_CONST char *buffer, TRIO_CONST char *format, va_list args));
|
||||
int trio_sscanfv TRIO_PROTO((TRIO_CONST char *buffer, TRIO_CONST char *format, void **args));
|
||||
|
||||
/*************************************************************************
|
||||
* Locale Functions
|
||||
*/
|
||||
void trio_locale_set_decimal_point TRIO_PROTO((char *decimalPoint));
|
||||
void trio_locale_set_thousand_separator TRIO_PROTO((char *thousandSeparator));
|
||||
void trio_locale_set_grouping TRIO_PROTO((char *grouping));
|
||||
|
||||
/*************************************************************************
|
||||
* Renaming
|
||||
*/
|
||||
#ifdef TRIO_REPLACE_STDIO
|
||||
/* Replace the <stdio.h> functions */
|
||||
#ifndef HAVE_PRINTF
|
||||
# define printf trio_printf
|
||||
#endif
|
||||
#ifndef HAVE_VPRINTF
|
||||
# define vprintf trio_vprintf
|
||||
#endif
|
||||
#ifndef HAVE_FPRINTF
|
||||
# define fprintf trio_fprintf
|
||||
#endif
|
||||
#ifndef HAVE_VFPRINTF
|
||||
# define vfprintf trio_vfprintf
|
||||
#endif
|
||||
#ifndef HAVE_SPRINTF
|
||||
# define sprintf trio_sprintf
|
||||
#endif
|
||||
#ifndef HAVE_VSPRINTF
|
||||
# define vsprintf trio_vsprintf
|
||||
#endif
|
||||
#ifndef HAVE_SNPRINTF
|
||||
# define snprintf trio_snprintf
|
||||
#endif
|
||||
#ifndef HAVE_VSNPRINTF
|
||||
# define vsnprintf trio_vsnprintf
|
||||
#endif
|
||||
#ifndef HAVE_SCANF
|
||||
# define scanf trio_scanf
|
||||
#endif
|
||||
#ifndef HAVE_VSCANF
|
||||
# define vscanf trio_vscanf
|
||||
#endif
|
||||
#ifndef HAVE_FSCANF
|
||||
# define fscanf trio_fscanf
|
||||
#endif
|
||||
#ifndef HAVE_VFSCANF
|
||||
# define vfscanf trio_vfscanf
|
||||
#endif
|
||||
#ifndef HAVE_SSCANF
|
||||
# define sscanf trio_sscanf
|
||||
#endif
|
||||
#ifndef HAVE_VSSCANF
|
||||
# define vsscanf trio_vsscanf
|
||||
#endif
|
||||
/* These aren't stdio functions, but we make them look similar */
|
||||
#define dprintf trio_dprintf
|
||||
#define vdprintf trio_vdprintf
|
||||
#define aprintf trio_aprintf
|
||||
#define vaprintf trio_vaprintf
|
||||
#define asprintf trio_asprintf
|
||||
#define vasprintf trio_vasprintf
|
||||
#define dscanf trio_dscanf
|
||||
#define vdscanf trio_vdscanf
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* WITHOUT_TRIO */
|
||||
|
||||
#endif /* TRIO_TRIO_H */
|
206
glib/trio/triodef.h
Normal file
206
glib/trio/triodef.h
Normal file
@ -0,0 +1,206 @@
|
||||
/*************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2001 Bjorn Reese <breese@users.sourceforge.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
|
||||
* CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
#ifndef TRIO_TRIODEF_H
|
||||
#define TRIO_TRIODEF_H
|
||||
|
||||
/*************************************************************************
|
||||
* Platform and compiler support detection
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
# define TRIO_COMPILER_GCC
|
||||
#elif defined(__SUNPRO_C)
|
||||
# define TRIO_COMPILER_SUNPRO
|
||||
#elif defined(__SUNPRO_CC)
|
||||
# define TRIO_COMPILER_SUNPRO
|
||||
# define __SUNPRO_C __SUNPRO_CC
|
||||
#elif defined(__xlC__) || defined(__IBMC__) || defined(__IBMCPP__)
|
||||
# define TRIO_COMPILER_XLC
|
||||
#elif defined(_AIX) && !defined(__GNUC__)
|
||||
# define TRIO_COMPILER_XLC /* Workaround for old xlc */
|
||||
#elif defined(__DECC) || defined(__DECCXX)
|
||||
# define TRIO_COMPILER_DECC
|
||||
#elif defined(__osf__) && defined(__LANGUAGE_C__)
|
||||
# define TRIO_COMPILER_DECC /* Workaround for old DEC C compilers */
|
||||
#elif defined(_MSC_VER)
|
||||
# define TRIO_COMPILER_MSVC
|
||||
#elif defined(__BORLANDC__)
|
||||
# define TRIO_COMPILER_BCB
|
||||
#endif
|
||||
|
||||
#if defined(VMS) || defined(__VMS)
|
||||
/*
|
||||
* VMS is placed first to avoid identifying the platform as Unix
|
||||
* based on the DECC compiler later on.
|
||||
*/
|
||||
# define TRIO_PLATFORM_VMS
|
||||
#elif defined(unix) || defined(__unix) || defined(__unix__)
|
||||
# define TRIO_PLATFORM_UNIX
|
||||
#elif defined(TRIO_COMPILER_XLC) || defined(_AIX)
|
||||
# define TRIO_PLATFORM_UNIX
|
||||
#elif defined(TRIO_COMPILER_DECC) || defined(__osf___)
|
||||
# define TRIO_PLATFORM_UNIX
|
||||
#elif defined(__NetBSD__)
|
||||
# define TRIO_PLATFORM_UNIX
|
||||
#elif defined(__QNX__)
|
||||
# define TRIO_PLATFORM_UNIX
|
||||
# define TRIO_PLATFORM_QNX
|
||||
#elif defined(__CYGWIN__)
|
||||
# define TRIO_PLATFORM_UNIX
|
||||
#elif defined(AMIGA) && defined(TRIO_COMPILER_GCC)
|
||||
# define TRIO_PLATFORM_UNIX
|
||||
#elif defined(TRIO_COMPILER_MSVC) || defined(WIN32) || defined(_WIN32)
|
||||
# define TRIO_PLATFORM_WIN32
|
||||
#elif defined(mpeix) || defined(__mpexl)
|
||||
# define TRIO_PLATFORM_MPEIX
|
||||
#endif
|
||||
|
||||
#if defined(_AIX)
|
||||
# define TRIO_PLATFORM_AIX
|
||||
#elif defined(__hpux)
|
||||
# define TRIO_PLATFORM_HPUX
|
||||
#endif
|
||||
|
||||
#if defined(__STDC__) || defined(TRIO_COMPILER_MSVC)
|
||||
# define TRIO_COMPILER_SUPPORTS_C89
|
||||
# if defined(__STDC_VERSION__)
|
||||
# define TRIO_COMPILER_SUPPORTS_C90
|
||||
# if (__STDC_VERSION__ >= 199409L)
|
||||
# define TRIO_COMPILER_SUPPORTS_C94
|
||||
# endif
|
||||
# if (__STDC_VERSION__ >= 199901L)
|
||||
# define TRIO_COMPILER_SUPPORTS_C99
|
||||
# endif
|
||||
# elif defined(TRIO_COMPILER_SUNPRO)
|
||||
# if (__SUNPRO_C >= 0x420)
|
||||
# define TRIO_COMPILER_SUPPORTS_C94
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(_XOPEN_SOURCE)
|
||||
# if defined(_XOPEN_SOURCE_EXTENDED)
|
||||
# define TRIO_COMPILER_SUPPORTS_UNIX95
|
||||
# endif
|
||||
# if (_XOPEN_VERSION >= 500)
|
||||
# define TRIO_COMPILER_SUPPORTS_UNIX98
|
||||
# endif
|
||||
# if (_XOPEN_VERSION >= 600)
|
||||
# define TRIO_COMPILER_SUPPORTS_UNIX01
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
* Generic defines
|
||||
*/
|
||||
|
||||
#if !defined(TRIO_PUBLIC)
|
||||
# define TRIO_PUBLIC
|
||||
#endif
|
||||
#if !defined(TRIO_PRIVATE)
|
||||
# define TRIO_PRIVATE static
|
||||
#endif
|
||||
|
||||
#if !(defined(TRIO_COMPILER_SUPPORTS_C89) || defined(__cplusplus))
|
||||
# define TRIO_COMPILER_ANCIENT
|
||||
#endif
|
||||
|
||||
#if defined(TRIO_COMPILER_ANCIENT)
|
||||
# define TRIO_CONST
|
||||
# define TRIO_VOLATILE
|
||||
# define TRIO_SIGNED
|
||||
typedef double trio_long_double_t;
|
||||
typedef char * trio_pointer_t;
|
||||
# define TRIO_SUFFIX_LONG(x) x
|
||||
# define TRIO_PROTO(x) ()
|
||||
# define TRIO_NOARGS
|
||||
# define TRIO_ARGS1(list,a1) list a1;
|
||||
# define TRIO_ARGS2(list,a1,a2) list a1; a2;
|
||||
# define TRIO_ARGS3(list,a1,a2,a3) list a1; a2; a3;
|
||||
# define TRIO_ARGS4(list,a1,a2,a3,a4) list a1; a2; a3; a4;
|
||||
# define TRIO_ARGS5(list,a1,a2,a3,a4,a5) list a1; a2; a3; a4; a5;
|
||||
# define TRIO_ARGS6(list,a1,a2,a3,a4,a5,a6) list a1; a2; a3; a4; a5; a6;
|
||||
# define TRIO_VARGS2(list,a1,a2) list a1; a2
|
||||
# define TRIO_VARGS3(list,a1,a2,a3) list a1; a2; a3
|
||||
# define TRIO_VARGS4(list,a1,a2,a3,a4) list a1; a2; a3; a4
|
||||
# define TRIO_VARGS5(list,a1,a2,a3,a4,a5) list a1; a2; a3; a4; a5
|
||||
# define TRIO_VA_DECL va_dcl
|
||||
# define TRIO_VA_START(x,y) va_start((x))
|
||||
# define TRIO_VA_END(x) va_end(x)
|
||||
#else /* ANSI C */
|
||||
# define TRIO_CONST const
|
||||
# define TRIO_VOLATILE volatile
|
||||
# define TRIO_SIGNED signed
|
||||
typedef long double trio_long_double_t;
|
||||
typedef void * trio_pointer_t;
|
||||
# define TRIO_SUFFIX_LONG(x) x ## L
|
||||
# define TRIO_PROTO(x) x
|
||||
# define TRIO_NOARGS void
|
||||
# define TRIO_ARGS1(list,a1) (a1)
|
||||
# define TRIO_ARGS2(list,a1,a2) (a1,a2)
|
||||
# define TRIO_ARGS3(list,a1,a2,a3) (a1,a2,a3)
|
||||
# define TRIO_ARGS4(list,a1,a2,a3,a4) (a1,a2,a3,a4)
|
||||
# define TRIO_ARGS5(list,a1,a2,a3,a4,a5) (a1,a2,a3,a4,a5)
|
||||
# define TRIO_ARGS6(list,a1,a2,a3,a4,a5,a6) (a1,a2,a3,a4,a5,a6)
|
||||
# define TRIO_VARGS2 TRIO_ARGS2
|
||||
# define TRIO_VARGS3 TRIO_ARGS3
|
||||
# define TRIO_VARGS4 TRIO_ARGS4
|
||||
# define TRIO_VARGS5 TRIO_ARGS5
|
||||
# define TRIO_VA_DECL ...
|
||||
# define TRIO_VA_START(x,y) va_start((x),(y))
|
||||
# define TRIO_VA_END(x) va_end(x)
|
||||
#endif
|
||||
|
||||
#if defined(TRIO_COMPILER_SUPPORTS_C99) || defined(__cplusplus)
|
||||
# define TRIO_INLINE inline
|
||||
#elif defined(TRIO_COMPILER_GCC)
|
||||
# define TRIO_INLINE __inline__
|
||||
#elif defined(TRIO_COMPILER_MSVC)
|
||||
# define TRIO_INLINE _inline
|
||||
#elif defined(TRIO_COMPILER_BCB)
|
||||
# define TRIO_INLINE __inline
|
||||
#else
|
||||
# define TRIO_INLINE
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
* Workarounds
|
||||
*/
|
||||
|
||||
#if defined(TRIO_PLATFORM_VMS)
|
||||
/*
|
||||
* Computations done with constants at compile time can trigger these
|
||||
* even when compiling with IEEE enabled.
|
||||
*/
|
||||
# pragma message disable (UNDERFLOW, FLOATOVERFL)
|
||||
|
||||
# if (__CRTL_VER > 80000000)
|
||||
/*
|
||||
* Although the compiler supports C99 language constructs, the C
|
||||
* run-time library does not contain all C99 functions.
|
||||
*
|
||||
* This was the case for 70300022. Update the 80000000 value when
|
||||
* it has been accurately determined what version of the library
|
||||
* supports C99.
|
||||
*/
|
||||
# if defined(TRIO_COMPILER_SUPPORTS_C99)
|
||||
# undef TRIO_COMPILER_SUPPORTS_C99
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* TRIO_TRIODEF_H */
|
925
glib/trio/trionan.c
Normal file
925
glib/trio/trionan.c
Normal file
@ -0,0 +1,925 @@
|
||||
/*************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2001 Bjorn Reese <breese@users.sourceforge.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
|
||||
* CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
|
||||
*
|
||||
************************************************************************
|
||||
*
|
||||
* Functions to handle special quantities in floating-point numbers
|
||||
* (that is, NaNs and infinity). They provide the capability to detect
|
||||
* and fabricate special quantities.
|
||||
*
|
||||
* Although written to be as portable as possible, it can never be
|
||||
* guaranteed to work on all platforms, as not all hardware supports
|
||||
* special quantities.
|
||||
*
|
||||
* The approach used here (approximately) is to:
|
||||
*
|
||||
* 1. Use C99 functionality when available.
|
||||
* 2. Use IEEE 754 bit-patterns if possible.
|
||||
* 3. Use platform-specific techniques.
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* o Put all the magic into trio_fpclassify_and_signbit(), and use this from
|
||||
* trio_isnan() etc.
|
||||
*/
|
||||
|
||||
/*************************************************************************
|
||||
* Include files
|
||||
*/
|
||||
#include "triodef.h"
|
||||
#include "trionan.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <float.h>
|
||||
#if defined(TRIO_PLATFORM_UNIX)
|
||||
# include <signal.h>
|
||||
#endif
|
||||
#if defined(TRIO_COMPILER_DECC)
|
||||
# include <fp_class.h>
|
||||
#endif
|
||||
#include <assert.h>
|
||||
|
||||
#if defined(TRIO_DOCUMENTATION)
|
||||
# include "doc/doc_nan.h"
|
||||
#endif
|
||||
/** @addtogroup SpecialQuantities
|
||||
@{
|
||||
*/
|
||||
|
||||
/*************************************************************************
|
||||
* Definitions
|
||||
*/
|
||||
|
||||
#define TRIO_TRUE (1 == 1)
|
||||
#define TRIO_FALSE (0 == 1)
|
||||
|
||||
/* We must enable IEEE floating-point on Alpha */
|
||||
#if defined(__alpha) && !defined(_IEEE_FP)
|
||||
# if defined(TRIO_COMPILER_DECC)
|
||||
# if defined(TRIO_PLATFORM_VMS)
|
||||
# error "Must be compiled with option /IEEE_MODE=UNDERFLOW_TO_ZERO/FLOAT=IEEE"
|
||||
# else
|
||||
# if !defined(_CFE)
|
||||
# error "Must be compiled with option -ieee"
|
||||
# endif
|
||||
# endif
|
||||
# elif defined(TRIO_COMPILER_GCC) && (defined(__osf__) || defined(__linux__))
|
||||
# error "Must be compiled with option -mieee"
|
||||
# endif
|
||||
#endif /* __alpha && ! _IEEE_FP */
|
||||
|
||||
/*
|
||||
* In ANSI/IEEE 754-1985 64-bits double format numbers have the
|
||||
* following properties (amoungst others)
|
||||
*
|
||||
* o FLT_RADIX == 2: binary encoding
|
||||
* o DBL_MAX_EXP == 1024: 11 bits exponent, where one bit is used
|
||||
* to indicate special numbers (e.g. NaN and Infinity), so the
|
||||
* maximum exponent is 10 bits wide (2^10 == 1024).
|
||||
* o DBL_MANT_DIG == 53: The mantissa is 52 bits wide, but because
|
||||
* numbers are normalized the initial binary 1 is represented
|
||||
* implicitly (the so-called "hidden bit"), which leaves us with
|
||||
* the ability to represent 53 bits wide mantissa.
|
||||
*/
|
||||
#if (FLT_RADIX == 2) && (DBL_MAX_EXP == 1024) && (DBL_MANT_DIG == 53)
|
||||
# define USE_IEEE_754
|
||||
#endif
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* Constants
|
||||
*/
|
||||
|
||||
static TRIO_CONST char rcsid[] = "@(#)$Id$";
|
||||
|
||||
#if defined(USE_IEEE_754)
|
||||
|
||||
/*
|
||||
* Endian-agnostic indexing macro.
|
||||
*
|
||||
* The value of internalEndianMagic, when converted into a 64-bit
|
||||
* integer, becomes 0x0706050403020100 (we could have used a 64-bit
|
||||
* integer value instead of a double, but not all platforms supports
|
||||
* that type). The value is automatically encoded with the correct
|
||||
* endianess by the compiler, which means that we can support any
|
||||
* kind of endianess. The individual bytes are then used as an index
|
||||
* for the IEEE 754 bit-patterns and masks.
|
||||
*/
|
||||
#define TRIO_DOUBLE_INDEX(x) (((unsigned char *)&internalEndianMagic)[7-(x)])
|
||||
|
||||
static TRIO_CONST double internalEndianMagic = 7.949928895127363e-275;
|
||||
|
||||
/* Mask for the exponent */
|
||||
static TRIO_CONST unsigned char ieee_754_exponent_mask[] = {
|
||||
0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
/* Mask for the mantissa */
|
||||
static TRIO_CONST unsigned char ieee_754_mantissa_mask[] = {
|
||||
0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
|
||||
/* Mask for the sign bit */
|
||||
static TRIO_CONST unsigned char ieee_754_sign_mask[] = {
|
||||
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
/* Bit-pattern for negative zero */
|
||||
static TRIO_CONST unsigned char ieee_754_negzero_array[] = {
|
||||
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
/* Bit-pattern for infinity */
|
||||
static TRIO_CONST unsigned char ieee_754_infinity_array[] = {
|
||||
0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
/* Bit-pattern for quiet NaN */
|
||||
static TRIO_CONST unsigned char ieee_754_qnan_array[] = {
|
||||
0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* Functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* trio_make_double
|
||||
*/
|
||||
TRIO_PRIVATE double
|
||||
trio_make_double
|
||||
TRIO_ARGS1((values),
|
||||
TRIO_CONST unsigned char *values)
|
||||
{
|
||||
TRIO_VOLATILE double result;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < (int)sizeof(double); i++) {
|
||||
((TRIO_VOLATILE unsigned char *)&result)[TRIO_DOUBLE_INDEX(i)] = values[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* trio_is_special_quantity
|
||||
*/
|
||||
TRIO_PRIVATE int
|
||||
trio_is_special_quantity
|
||||
TRIO_ARGS2((number, has_mantissa),
|
||||
double number,
|
||||
int *has_mantissa)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned char current;
|
||||
int is_special_quantity = TRIO_TRUE;
|
||||
|
||||
*has_mantissa = 0;
|
||||
|
||||
for (i = 0; i < (unsigned int)sizeof(double); i++) {
|
||||
current = ((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)];
|
||||
is_special_quantity
|
||||
&= ((current & ieee_754_exponent_mask[i]) == ieee_754_exponent_mask[i]);
|
||||
*has_mantissa |= (current & ieee_754_mantissa_mask[i]);
|
||||
}
|
||||
return is_special_quantity;
|
||||
}
|
||||
|
||||
/*
|
||||
* trio_is_negative
|
||||
*/
|
||||
TRIO_PRIVATE int
|
||||
trio_is_negative
|
||||
TRIO_ARGS1((number),
|
||||
double number)
|
||||
{
|
||||
unsigned int i;
|
||||
int is_negative = TRIO_FALSE;
|
||||
|
||||
for (i = 0; i < (unsigned int)sizeof(double); i++) {
|
||||
is_negative |= (((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)]
|
||||
& ieee_754_sign_mask[i]);
|
||||
}
|
||||
return is_negative;
|
||||
}
|
||||
|
||||
#endif /* USE_IEEE_754 */
|
||||
|
||||
|
||||
/**
|
||||
Generate negative zero.
|
||||
|
||||
@return Floating-point representation of negative zero.
|
||||
*/
|
||||
TRIO_PUBLIC double
|
||||
trio_nzero(TRIO_NOARGS)
|
||||
{
|
||||
#if defined(USE_IEEE_754)
|
||||
return trio_make_double(ieee_754_negzero_array);
|
||||
#else
|
||||
TRIO_VOLATILE double zero = 0.0;
|
||||
|
||||
return -zero;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
Generate positive infinity.
|
||||
|
||||
@return Floating-point representation of positive infinity.
|
||||
*/
|
||||
TRIO_PUBLIC double
|
||||
trio_pinf(TRIO_NOARGS)
|
||||
{
|
||||
/* Cache the result */
|
||||
static double result = 0.0;
|
||||
|
||||
if (result == 0.0) {
|
||||
|
||||
#if defined(INFINITY) && defined(__STDC_IEC_559__)
|
||||
result = (double)INFINITY;
|
||||
|
||||
#elif defined(USE_IEEE_754)
|
||||
result = trio_make_double(ieee_754_infinity_array);
|
||||
|
||||
#else
|
||||
/*
|
||||
* If HUGE_VAL is different from DBL_MAX, then HUGE_VAL is used
|
||||
* as infinity. Otherwise we have to resort to an overflow
|
||||
* operation to generate infinity.
|
||||
*/
|
||||
# if defined(TRIO_PLATFORM_UNIX)
|
||||
void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
|
||||
# endif
|
||||
|
||||
result = HUGE_VAL;
|
||||
if (HUGE_VAL == DBL_MAX) {
|
||||
/* Force overflow */
|
||||
result += HUGE_VAL;
|
||||
}
|
||||
|
||||
# if defined(TRIO_PLATFORM_UNIX)
|
||||
signal(SIGFPE, signal_handler);
|
||||
# endif
|
||||
|
||||
#endif
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
Generate negative infinity.
|
||||
|
||||
@return Floating-point value of negative infinity.
|
||||
*/
|
||||
TRIO_PUBLIC double
|
||||
trio_ninf(TRIO_NOARGS)
|
||||
{
|
||||
static double result = 0.0;
|
||||
|
||||
if (result == 0.0) {
|
||||
/*
|
||||
* Negative infinity is calculated by negating positive infinity,
|
||||
* which can be done because it is legal to do calculations on
|
||||
* infinity (for example, 1 / infinity == 0).
|
||||
*/
|
||||
result = -trio_pinf();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
Generate NaN.
|
||||
|
||||
@return Floating-point representation of NaN.
|
||||
*/
|
||||
TRIO_PUBLIC double
|
||||
trio_nan(TRIO_NOARGS)
|
||||
{
|
||||
/* Cache the result */
|
||||
static double result = 0.0;
|
||||
|
||||
if (result == 0.0) {
|
||||
|
||||
#if defined(TRIO_COMPILER_SUPPORTS_C99)
|
||||
result = nan("");
|
||||
|
||||
#elif defined(NAN) && defined(__STDC_IEC_559__)
|
||||
result = (double)NAN;
|
||||
|
||||
#elif defined(USE_IEEE_754)
|
||||
result = trio_make_double(ieee_754_qnan_array);
|
||||
|
||||
#else
|
||||
/*
|
||||
* There are several ways to generate NaN. The one used here is
|
||||
* to divide infinity by infinity. I would have preferred to add
|
||||
* negative infinity to positive infinity, but that yields wrong
|
||||
* result (infinity) on FreeBSD.
|
||||
*
|
||||
* This may fail if the hardware does not support NaN, or if
|
||||
* the Invalid Operation floating-point exception is unmasked.
|
||||
*/
|
||||
# if defined(TRIO_PLATFORM_UNIX)
|
||||
void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
|
||||
# endif
|
||||
|
||||
result = trio_pinf() / trio_pinf();
|
||||
|
||||
# if defined(TRIO_PLATFORM_UNIX)
|
||||
signal(SIGFPE, signal_handler);
|
||||
# endif
|
||||
|
||||
#endif
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
Check for NaN.
|
||||
|
||||
@param number An arbitrary floating-point number.
|
||||
@return Boolean value indicating whether or not the number is a NaN.
|
||||
*/
|
||||
TRIO_PUBLIC int
|
||||
trio_isnan
|
||||
TRIO_ARGS1((number),
|
||||
double number)
|
||||
{
|
||||
#if (defined(TRIO_COMPILER_SUPPORTS_C99) && defined(isnan)) \
|
||||
|| defined(TRIO_COMPILER_SUPPORTS_UNIX95)
|
||||
/*
|
||||
* C99 defines isnan() as a macro. UNIX95 defines isnan() as a
|
||||
* function. This function was already present in XPG4, but this
|
||||
* is a bit tricky to detect with compiler defines, so we choose
|
||||
* the conservative approach and only use it for UNIX95.
|
||||
*/
|
||||
return isnan(number);
|
||||
|
||||
#elif defined(TRIO_COMPILER_MSVC)
|
||||
/*
|
||||
* MSVC has an _isnan() function
|
||||
*/
|
||||
return _isnan(number);
|
||||
|
||||
#elif defined(USE_IEEE_754)
|
||||
/*
|
||||
* Examine IEEE 754 bit-pattern. A NaN must have a special exponent
|
||||
* pattern, and a non-empty mantissa.
|
||||
*/
|
||||
int has_mantissa;
|
||||
int is_special_quantity;
|
||||
|
||||
is_special_quantity = trio_is_special_quantity(number, &has_mantissa);
|
||||
|
||||
return (is_special_quantity && has_mantissa);
|
||||
|
||||
#else
|
||||
/*
|
||||
* Fallback solution
|
||||
*/
|
||||
int status;
|
||||
double integral, fraction;
|
||||
|
||||
# if defined(TRIO_PLATFORM_UNIX)
|
||||
void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
|
||||
# endif
|
||||
|
||||
status = (/*
|
||||
* NaN is the only number which does not compare to itself
|
||||
*/
|
||||
((TRIO_VOLATILE double)number != (TRIO_VOLATILE double)number) ||
|
||||
/*
|
||||
* Fallback solution if NaN compares to NaN
|
||||
*/
|
||||
((number != 0.0) &&
|
||||
(fraction = modf(number, &integral),
|
||||
integral == fraction)));
|
||||
|
||||
# if defined(TRIO_PLATFORM_UNIX)
|
||||
signal(SIGFPE, signal_handler);
|
||||
# endif
|
||||
|
||||
return status;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
Check for infinity.
|
||||
|
||||
@param number An arbitrary floating-point number.
|
||||
@return 1 if positive infinity, -1 if negative infinity, 0 otherwise.
|
||||
*/
|
||||
TRIO_PUBLIC int
|
||||
trio_isinf
|
||||
TRIO_ARGS1((number),
|
||||
double number)
|
||||
{
|
||||
#if defined(TRIO_COMPILER_DECC)
|
||||
/*
|
||||
* DECC has an isinf() macro, but it works differently than that
|
||||
* of C99, so we use the fp_class() function instead.
|
||||
*/
|
||||
return ((fp_class(number) == FP_POS_INF)
|
||||
? 1
|
||||
: ((fp_class(number) == FP_NEG_INF) ? -1 : 0));
|
||||
|
||||
#elif defined(isinf)
|
||||
/*
|
||||
* C99 defines isinf() as a macro.
|
||||
*/
|
||||
return isinf(number)
|
||||
? ((number > 0.0) ? 1 : -1)
|
||||
: 0;
|
||||
|
||||
#elif defined(TRIO_COMPILER_MSVC)
|
||||
/*
|
||||
* MSVC has an _fpclass() function that can be used to detect infinity.
|
||||
*/
|
||||
return ((_fpclass(number) == _FPCLASS_PINF)
|
||||
? 1
|
||||
: ((_fpclass(number) == _FPCLASS_NINF) ? -1 : 0));
|
||||
|
||||
#elif defined(USE_IEEE_754)
|
||||
/*
|
||||
* Examine IEEE 754 bit-pattern. Infinity must have a special exponent
|
||||
* pattern, and an empty mantissa.
|
||||
*/
|
||||
int has_mantissa;
|
||||
int is_special_quantity;
|
||||
|
||||
is_special_quantity = trio_is_special_quantity(number, &has_mantissa);
|
||||
|
||||
return (is_special_quantity && !has_mantissa)
|
||||
? ((number < 0.0) ? -1 : 1)
|
||||
: 0;
|
||||
|
||||
#else
|
||||
/*
|
||||
* Fallback solution.
|
||||
*/
|
||||
int status;
|
||||
|
||||
# if defined(TRIO_PLATFORM_UNIX)
|
||||
void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
|
||||
# endif
|
||||
|
||||
double infinity = trio_pinf();
|
||||
|
||||
status = ((number == infinity)
|
||||
? 1
|
||||
: ((number == -infinity) ? -1 : 0));
|
||||
|
||||
# if defined(TRIO_PLATFORM_UNIX)
|
||||
signal(SIGFPE, signal_handler);
|
||||
# endif
|
||||
|
||||
return status;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Check for finity.
|
||||
|
||||
@param number An arbitrary floating-point number.
|
||||
@return Boolean value indicating whether or not the number is a finite.
|
||||
*/
|
||||
TRIO_PUBLIC int
|
||||
trio_isfinite
|
||||
TRIO_ARGS1((number),
|
||||
double number)
|
||||
{
|
||||
#if defined(TRIO_COMPILER_SUPPORTS_C99) && defined(isfinite)
|
||||
/*
|
||||
* C99 defines isfinite() as a macro.
|
||||
*/
|
||||
return isfinite(number);
|
||||
|
||||
#elif defined(TRIO_COMPILER_MSVC)
|
||||
/*
|
||||
* MSVC uses _finite().
|
||||
*/
|
||||
return _finite(number);
|
||||
|
||||
#elif defined(USE_IEEE_754)
|
||||
/*
|
||||
* Examine IEEE 754 bit-pattern. For finity we do not care about the
|
||||
* mantissa.
|
||||
*/
|
||||
int dummy;
|
||||
|
||||
return (! trio_is_special_quantity(number, &dummy));
|
||||
|
||||
#else
|
||||
/*
|
||||
* Fallback solution.
|
||||
*/
|
||||
return ((trio_isinf(number) == 0) && (trio_isnan(number) == 0));
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* The sign of NaN is always false
|
||||
*/
|
||||
TRIO_PUBLIC int
|
||||
trio_fpclassify_and_signbit
|
||||
TRIO_ARGS2((number, is_negative),
|
||||
double number,
|
||||
int *is_negative)
|
||||
{
|
||||
#if defined(fpclassify) && defined(signbit)
|
||||
/*
|
||||
* C99 defines fpclassify() and signbit() as a macros
|
||||
*/
|
||||
*is_negative = signbit(number);
|
||||
switch (fpclassify(number)) {
|
||||
case FP_NAN:
|
||||
return TRIO_FP_NAN;
|
||||
case FP_INFINITE:
|
||||
return TRIO_FP_INFINITE;
|
||||
case FP_SUBNORMAL:
|
||||
return TRIO_FP_SUBNORMAL;
|
||||
case FP_ZERO:
|
||||
return TRIO_FP_ZERO;
|
||||
default:
|
||||
return TRIO_FP_NORMAL;
|
||||
}
|
||||
|
||||
#elif defined(TRIO_COMPILER_DECC)
|
||||
/*
|
||||
* DECC has an fp_class() function.
|
||||
*/
|
||||
switch (fp_class(number)) {
|
||||
case FP_QNAN:
|
||||
case FP_SNAN:
|
||||
*is_negative = TRIO_FALSE; /* NaN has no sign */
|
||||
return TRIO_FP_NAN;
|
||||
case FP_POS_INF:
|
||||
*is_negative = TRIO_FALSE;
|
||||
return TRIO_FP_INFINITE;
|
||||
case FP_NEG_INF:
|
||||
*is_negative = TRIO_TRUE;
|
||||
return TRIO_FP_INFINITE;
|
||||
case FP_POS_DENORM:
|
||||
*is_negative = TRIO_FALSE;
|
||||
return TRIO_FP_SUBNORMAL;
|
||||
case FP_NEG_DENORM:
|
||||
*is_negative = TRIO_TRUE;
|
||||
return TRIO_FP_SUBNORMAL;
|
||||
case FP_POS_ZERO:
|
||||
*is_negative = TRIO_FALSE;
|
||||
return TRIO_FP_ZERO;
|
||||
case FP_NEG_ZERO:
|
||||
*is_negative = TRIO_TRUE;
|
||||
return TRIO_FP_ZERO;
|
||||
case FP_POS_NORM:
|
||||
*is_negative = TRIO_FALSE;
|
||||
return TRIO_FP_NORMAL;
|
||||
case FP_NEG_NORM:
|
||||
*is_negative = TRIO_TRUE;
|
||||
return TRIO_FP_NORMAL;
|
||||
default:
|
||||
/* Just in case... */
|
||||
*is_negative = (number < 0.0);
|
||||
return TRIO_FP_NORMAL;
|
||||
}
|
||||
|
||||
#elif defined(TRIO_COMPILER_MSVC)
|
||||
/*
|
||||
* MSVC has an _fpclass() function.
|
||||
*/
|
||||
switch (_fpclass(number)) {
|
||||
case _FPCLASS_QNAN:
|
||||
case _FPCLASS_SNAN:
|
||||
*is_negative = TRIO_FALSE;
|
||||
return TRIO_FP_NAN;
|
||||
case _FPCLASS_PINF:
|
||||
*is_negative = TRIO_FALSE;
|
||||
return TRIO_FP_INFINITE;
|
||||
case _FPCLASS_NINF:
|
||||
*is_negative = TRIO_TRUE;
|
||||
return TRIO_FP_INFINITE;
|
||||
case _FPCLASS_PD:
|
||||
*is_negative = TRIO_FALSE;
|
||||
return TRIO_FP_SUBNORMAL;
|
||||
case _FPCLASS_ND:
|
||||
*is_negative = TRIO_TRUE;
|
||||
return TRIO_FP_SUBNORMAL;
|
||||
case _FPCLASS_PZ:
|
||||
*is_negative = TRIO_FALSE;
|
||||
return TRIO_FP_ZERO;
|
||||
case _FPCLASS_NZ:
|
||||
*is_negative = TRIO_TRUE;
|
||||
return TRIO_FP_ZERO;
|
||||
case _FPCLASS_PN:
|
||||
*is_negative = TRIO_FALSE;
|
||||
return TRIO_FP_NORMAL;
|
||||
case _FPCLASS_NN:
|
||||
*is_negative = TRIO_TRUE;
|
||||
return TRIO_FP_NORMAL;
|
||||
default:
|
||||
/* Just in case... */
|
||||
*is_negative = (number < 0.0);
|
||||
return TRIO_FP_NORMAL;
|
||||
}
|
||||
|
||||
#elif defined(FP_PLUS_NORM)
|
||||
|
||||
/*
|
||||
* HP-UX 9.x and 10.x have an fpclassify() function, that is different
|
||||
* from the C99 fpclassify() macro supported on HP-UX 11.x.
|
||||
*
|
||||
* AIX has class() for C, and _class() for C++, which returns the
|
||||
* same values as the HP-UX fpclassify() function.
|
||||
*/
|
||||
|
||||
# if defined(TRIO_PLATFORM_AIX)
|
||||
# if defined(__cplusplus)
|
||||
# define fpclassify(x) _class(x)
|
||||
# else
|
||||
# define fpclassify(x) class(x)
|
||||
# endif
|
||||
# endif
|
||||
|
||||
switch (fpclassify(number)) {
|
||||
case FP_QNAN:
|
||||
case FP_SNAN:
|
||||
*is_negative = TRIO_FALSE;
|
||||
return TRIO_FP_NAN;
|
||||
case FP_PLUS_INF:
|
||||
*is_negative = TRIO_FALSE;
|
||||
return TRIO_FP_INFINITE;
|
||||
case FP_MINUS_INF:
|
||||
*is_negative = TRIO_TRUE;
|
||||
return TRIO_FP_INFINITE;
|
||||
case FP_PLUS_DENORM:
|
||||
*is_negative = TRIO_FALSE;
|
||||
return TRIO_FP_SUBNORMAL;
|
||||
case FP_MINUS_DENORM:
|
||||
*is_negative = TRIO_TRUE;
|
||||
return TRIO_FP_SUBNORMAL;
|
||||
case FP_PLUS_ZERO:
|
||||
*is_negative = TRIO_FALSE;
|
||||
return TRIO_FP_ZERO;
|
||||
case FP_MINUS_ZERO:
|
||||
*is_negative = TRIO_TRUE;
|
||||
return TRIO_FP_ZERO;
|
||||
case FP_PLUS_NORM:
|
||||
*is_negative = TRIO_FALSE;
|
||||
return TRIO_FP_NORMAL;
|
||||
case FP_MINUS_NORM:
|
||||
*is_negative = TRIO_TRUE;
|
||||
return TRIO_FP_NORMAL;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
#else
|
||||
/*
|
||||
* Fallback solution.
|
||||
*/
|
||||
int rc;
|
||||
|
||||
if (number == 0.0) {
|
||||
/*
|
||||
* In IEEE 754 the sign of zero is ignored in comparisons, so we
|
||||
* have to handle this as a special case by examining the sign bit
|
||||
* directly.
|
||||
*/
|
||||
#if defined(USE_IEEE_754)
|
||||
*is_negative = trio_is_negative(number);
|
||||
#else
|
||||
*is_negative = TRIO_FALSE; /* FIXME */
|
||||
#endif
|
||||
return TRIO_FP_ZERO;
|
||||
}
|
||||
if (trio_isnan(number)) {
|
||||
*is_negative = TRIO_FALSE;
|
||||
return TRIO_FP_NAN;
|
||||
}
|
||||
if ((rc = trio_isinf(number))) {
|
||||
*is_negative = (rc == -1);
|
||||
return TRIO_FP_INFINITE;
|
||||
}
|
||||
if ((number > 0.0) && (number < DBL_MIN)) {
|
||||
*is_negative = TRIO_FALSE;
|
||||
return TRIO_FP_SUBNORMAL;
|
||||
}
|
||||
if ((number < 0.0) && (number > -DBL_MIN)) {
|
||||
*is_negative = TRIO_TRUE;
|
||||
return TRIO_FP_SUBNORMAL;
|
||||
}
|
||||
*is_negative = (number < 0.0);
|
||||
return TRIO_FP_NORMAL;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
Examine the sign of a number.
|
||||
|
||||
@param number An arbitrary floating-point number.
|
||||
@return Boolean value indicating whether or not the number has the
|
||||
sign bit set (i.e. is negative).
|
||||
*/
|
||||
TRIO_PUBLIC int
|
||||
trio_signbit
|
||||
TRIO_ARGS1((number),
|
||||
double number)
|
||||
{
|
||||
int is_negative;
|
||||
|
||||
(void)trio_fpclassify_and_signbit(number, &is_negative);
|
||||
return is_negative;
|
||||
}
|
||||
|
||||
/**
|
||||
Examine the class of a number.
|
||||
|
||||
@param number An arbitrary floating-point number.
|
||||
@return Enumerable value indicating the class of @p number
|
||||
*/
|
||||
TRIO_PUBLIC int
|
||||
trio_fpclassify
|
||||
TRIO_ARGS1((number),
|
||||
double number)
|
||||
{
|
||||
int dummy;
|
||||
|
||||
return trio_fpclassify_and_signbit(number, &dummy);
|
||||
}
|
||||
|
||||
|
||||
/** @} SpecialQuantities */
|
||||
|
||||
/*************************************************************************
|
||||
* For test purposes.
|
||||
*
|
||||
* Add the following compiler option to include this test code.
|
||||
*
|
||||
* Unix : -DSTANDALONE
|
||||
* VMS : /DEFINE=(STANDALONE)
|
||||
*/
|
||||
#if defined(STANDALONE)
|
||||
# include <stdio.h>
|
||||
|
||||
static TRIO_CONST char *
|
||||
getClassification
|
||||
TRIO_ARGS1((type),
|
||||
int type)
|
||||
{
|
||||
switch (type) {
|
||||
case TRIO_FP_INFINITE:
|
||||
return "FP_INFINITE";
|
||||
case TRIO_FP_NAN:
|
||||
return "FP_NAN";
|
||||
case TRIO_FP_NORMAL:
|
||||
return "FP_NORMAL";
|
||||
case TRIO_FP_SUBNORMAL:
|
||||
return "FP_SUBNORMAL";
|
||||
case TRIO_FP_ZERO:
|
||||
return "FP_ZERO";
|
||||
default:
|
||||
return "FP_UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_class
|
||||
TRIO_ARGS2((prefix, number),
|
||||
TRIO_CONST char *prefix,
|
||||
double number)
|
||||
{
|
||||
printf("%-6s: %s %-15s %g\n",
|
||||
prefix,
|
||||
trio_signbit(number) ? "-" : "+",
|
||||
getClassification(trio_fpclassify(number)),
|
||||
number);
|
||||
}
|
||||
|
||||
int main(TRIO_NOARGS)
|
||||
{
|
||||
double my_nan;
|
||||
double my_pinf;
|
||||
double my_ninf;
|
||||
# if defined(TRIO_PLATFORM_UNIX)
|
||||
void (*signal_handler) TRIO_PROTO((int));
|
||||
# endif
|
||||
|
||||
my_nan = trio_nan();
|
||||
my_pinf = trio_pinf();
|
||||
my_ninf = trio_ninf();
|
||||
|
||||
print_class("Nan", my_nan);
|
||||
print_class("PInf", my_pinf);
|
||||
print_class("NInf", my_ninf);
|
||||
print_class("PZero", 0.0);
|
||||
print_class("NZero", -0.0);
|
||||
print_class("PNorm", 1.0);
|
||||
print_class("NNorm", -1.0);
|
||||
print_class("PSub", 1.01e-307 - 1.00e-307);
|
||||
print_class("NSub", 1.00e-307 - 1.01e-307);
|
||||
|
||||
printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
|
||||
my_nan,
|
||||
((unsigned char *)&my_nan)[0],
|
||||
((unsigned char *)&my_nan)[1],
|
||||
((unsigned char *)&my_nan)[2],
|
||||
((unsigned char *)&my_nan)[3],
|
||||
((unsigned char *)&my_nan)[4],
|
||||
((unsigned char *)&my_nan)[5],
|
||||
((unsigned char *)&my_nan)[6],
|
||||
((unsigned char *)&my_nan)[7],
|
||||
trio_isnan(my_nan), trio_isinf(my_nan));
|
||||
printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
|
||||
my_pinf,
|
||||
((unsigned char *)&my_pinf)[0],
|
||||
((unsigned char *)&my_pinf)[1],
|
||||
((unsigned char *)&my_pinf)[2],
|
||||
((unsigned char *)&my_pinf)[3],
|
||||
((unsigned char *)&my_pinf)[4],
|
||||
((unsigned char *)&my_pinf)[5],
|
||||
((unsigned char *)&my_pinf)[6],
|
||||
((unsigned char *)&my_pinf)[7],
|
||||
trio_isnan(my_pinf), trio_isinf(my_pinf));
|
||||
printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
|
||||
my_ninf,
|
||||
((unsigned char *)&my_ninf)[0],
|
||||
((unsigned char *)&my_ninf)[1],
|
||||
((unsigned char *)&my_ninf)[2],
|
||||
((unsigned char *)&my_ninf)[3],
|
||||
((unsigned char *)&my_ninf)[4],
|
||||
((unsigned char *)&my_ninf)[5],
|
||||
((unsigned char *)&my_ninf)[6],
|
||||
((unsigned char *)&my_ninf)[7],
|
||||
trio_isnan(my_ninf), trio_isinf(my_ninf));
|
||||
|
||||
# if defined(TRIO_PLATFORM_UNIX)
|
||||
signal_handler = signal(SIGFPE, SIG_IGN);
|
||||
# endif
|
||||
|
||||
my_pinf = DBL_MAX + DBL_MAX;
|
||||
my_ninf = -my_pinf;
|
||||
my_nan = my_pinf / my_pinf;
|
||||
|
||||
# if defined(TRIO_PLATFORM_UNIX)
|
||||
signal(SIGFPE, signal_handler);
|
||||
# endif
|
||||
|
||||
printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
|
||||
my_nan,
|
||||
((unsigned char *)&my_nan)[0],
|
||||
((unsigned char *)&my_nan)[1],
|
||||
((unsigned char *)&my_nan)[2],
|
||||
((unsigned char *)&my_nan)[3],
|
||||
((unsigned char *)&my_nan)[4],
|
||||
((unsigned char *)&my_nan)[5],
|
||||
((unsigned char *)&my_nan)[6],
|
||||
((unsigned char *)&my_nan)[7],
|
||||
trio_isnan(my_nan), trio_isinf(my_nan));
|
||||
printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
|
||||
my_pinf,
|
||||
((unsigned char *)&my_pinf)[0],
|
||||
((unsigned char *)&my_pinf)[1],
|
||||
((unsigned char *)&my_pinf)[2],
|
||||
((unsigned char *)&my_pinf)[3],
|
||||
((unsigned char *)&my_pinf)[4],
|
||||
((unsigned char *)&my_pinf)[5],
|
||||
((unsigned char *)&my_pinf)[6],
|
||||
((unsigned char *)&my_pinf)[7],
|
||||
trio_isnan(my_pinf), trio_isinf(my_pinf));
|
||||
printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
|
||||
my_ninf,
|
||||
((unsigned char *)&my_ninf)[0],
|
||||
((unsigned char *)&my_ninf)[1],
|
||||
((unsigned char *)&my_ninf)[2],
|
||||
((unsigned char *)&my_ninf)[3],
|
||||
((unsigned char *)&my_ninf)[4],
|
||||
((unsigned char *)&my_ninf)[5],
|
||||
((unsigned char *)&my_ninf)[6],
|
||||
((unsigned char *)&my_ninf)[7],
|
||||
trio_isnan(my_ninf), trio_isinf(my_ninf));
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
81
glib/trio/trionan.h
Normal file
81
glib/trio/trionan.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2001 Bjorn Reese <breese@users.sourceforge.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
|
||||
* CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
#ifndef TRIO_NAN_H
|
||||
#define TRIO_NAN_H
|
||||
|
||||
#include "triodef.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum {
|
||||
TRIO_FP_INFINITE,
|
||||
TRIO_FP_NAN,
|
||||
TRIO_FP_NORMAL,
|
||||
TRIO_FP_SUBNORMAL,
|
||||
TRIO_FP_ZERO
|
||||
};
|
||||
|
||||
/*
|
||||
* Return NaN (Not-a-Number).
|
||||
*/
|
||||
TRIO_PUBLIC double trio_nan TRIO_PROTO((void));
|
||||
|
||||
/*
|
||||
* Return positive infinity.
|
||||
*/
|
||||
TRIO_PUBLIC double trio_pinf TRIO_PROTO((void));
|
||||
|
||||
/*
|
||||
* Return negative infinity.
|
||||
*/
|
||||
TRIO_PUBLIC double trio_ninf TRIO_PROTO((void));
|
||||
|
||||
/*
|
||||
* Return negative zero.
|
||||
*/
|
||||
TRIO_PUBLIC double trio_nzero TRIO_PROTO((TRIO_NOARGS));
|
||||
|
||||
/*
|
||||
* If number is a NaN return non-zero, otherwise return zero.
|
||||
*/
|
||||
TRIO_PUBLIC int trio_isnan TRIO_PROTO((double number));
|
||||
|
||||
/*
|
||||
* If number is positive infinity return 1, if number is negative
|
||||
* infinity return -1, otherwise return 0.
|
||||
*/
|
||||
TRIO_PUBLIC int trio_isinf TRIO_PROTO((double number));
|
||||
|
||||
/*
|
||||
* If number is finite return non-zero, otherwise return zero.
|
||||
*/
|
||||
TRIO_PUBLIC int trio_isfinite TRIO_PROTO((double number));
|
||||
|
||||
TRIO_PUBLIC int trio_signbit TRIO_PROTO((double number));
|
||||
|
||||
TRIO_PUBLIC int trio_fpclassify TRIO_PROTO((double number));
|
||||
|
||||
TRIO_PUBLIC int trio_fpclassify_and_signbit TRIO_PROTO((double number, int *is_negative));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TRIO_NAN_H */
|
150
glib/trio/triop.h
Normal file
150
glib/trio/triop.h
Normal file
@ -0,0 +1,150 @@
|
||||
/*************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2000 Bjorn Reese and Daniel Stenberg.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
|
||||
* CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
|
||||
*
|
||||
************************************************************************
|
||||
*
|
||||
* Private functions, types, etc. used for callback functions.
|
||||
*
|
||||
* The ref pointer is an opaque type and should remain as such.
|
||||
* Private data must only be accessible through the getter and
|
||||
* setter functions.
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
#ifndef TRIO_TRIOP_H
|
||||
#define TRIO_TRIOP_H
|
||||
|
||||
#include "triodef.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#if defined(TRIO_COMPILER_ANCIENT)
|
||||
# include <varargs.h>
|
||||
#else
|
||||
# include <stdarg.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef TRIO_C99
|
||||
# define TRIO_C99 1
|
||||
#endif
|
||||
#ifndef TRIO_BSD
|
||||
# define TRIO_BSD 1
|
||||
#endif
|
||||
#ifndef TRIO_GNU
|
||||
# define TRIO_GNU 1
|
||||
#endif
|
||||
#ifndef TRIO_MISC
|
||||
# define TRIO_MISC 1
|
||||
#endif
|
||||
#ifndef TRIO_UNIX98
|
||||
# define TRIO_UNIX98 1
|
||||
#endif
|
||||
#ifndef TRIO_MICROSOFT
|
||||
# define TRIO_MICROSOFT 1
|
||||
#endif
|
||||
#ifndef TRIO_EXTENSION
|
||||
# define TRIO_EXTENSION 1
|
||||
#endif
|
||||
#ifndef TRIO_WIDECHAR /* Does not work yet. Do not enable */
|
||||
# define TRIO_WIDECHAR 0
|
||||
#endif
|
||||
#ifndef TRIO_ERRORS
|
||||
# define TRIO_ERRORS 1
|
||||
#endif
|
||||
|
||||
#ifndef TRIO_MALLOC
|
||||
# define TRIO_MALLOC(n) malloc(n)
|
||||
#endif
|
||||
#ifndef TRIO_REALLOC
|
||||
# define TRIO_REALLOC(x,n) realloc((x),(n))
|
||||
#endif
|
||||
#ifndef TRIO_FREE
|
||||
# define TRIO_FREE(x) free(x)
|
||||
#endif
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* User-defined specifiers
|
||||
*/
|
||||
|
||||
typedef int (*trio_callback_t) TRIO_PROTO((trio_pointer_t));
|
||||
|
||||
trio_pointer_t trio_register TRIO_PROTO((trio_callback_t callback, const char *name));
|
||||
void trio_unregister TRIO_PROTO((trio_pointer_t handle));
|
||||
|
||||
TRIO_CONST char *trio_get_format TRIO_PROTO((trio_pointer_t ref));
|
||||
trio_pointer_t trio_get_argument TRIO_PROTO((trio_pointer_t ref));
|
||||
|
||||
/* Modifiers */
|
||||
int trio_get_width TRIO_PROTO((trio_pointer_t ref));
|
||||
void trio_set_width TRIO_PROTO((trio_pointer_t ref, int width));
|
||||
int trio_get_precision TRIO_PROTO((trio_pointer_t ref));
|
||||
void trio_set_precision TRIO_PROTO((trio_pointer_t ref, int precision));
|
||||
int trio_get_base TRIO_PROTO((trio_pointer_t ref));
|
||||
void trio_set_base TRIO_PROTO((trio_pointer_t ref, int base));
|
||||
int trio_get_padding TRIO_PROTO((trio_pointer_t ref));
|
||||
void trio_set_padding TRIO_PROTO((trio_pointer_t ref, int is_padding));
|
||||
int trio_get_short TRIO_PROTO((trio_pointer_t ref)); /* h */
|
||||
void trio_set_shortshort TRIO_PROTO((trio_pointer_t ref, int is_shortshort));
|
||||
int trio_get_shortshort TRIO_PROTO((trio_pointer_t ref)); /* hh */
|
||||
void trio_set_short TRIO_PROTO((trio_pointer_t ref, int is_short));
|
||||
int trio_get_long TRIO_PROTO((trio_pointer_t ref)); /* l */
|
||||
void trio_set_long TRIO_PROTO((trio_pointer_t ref, int is_long));
|
||||
int trio_get_longlong TRIO_PROTO((trio_pointer_t ref)); /* ll */
|
||||
void trio_set_longlong TRIO_PROTO((trio_pointer_t ref, int is_longlong));
|
||||
int trio_get_longdouble TRIO_PROTO((trio_pointer_t ref)); /* L */
|
||||
void trio_set_longdouble TRIO_PROTO((trio_pointer_t ref, int is_longdouble));
|
||||
int trio_get_alternative TRIO_PROTO((trio_pointer_t ref)); /* # */
|
||||
void trio_set_alternative TRIO_PROTO((trio_pointer_t ref, int is_alternative));
|
||||
int trio_get_alignment TRIO_PROTO((trio_pointer_t ref)); /* - */
|
||||
void trio_set_alignment TRIO_PROTO((trio_pointer_t ref, int is_leftaligned));
|
||||
int trio_get_spacing TRIO_PROTO((trio_pointer_t ref)); /* TRIO_PROTO((space) */
|
||||
void trio_set_spacing TRIO_PROTO((trio_pointer_t ref, int is_space));
|
||||
int trio_get_sign TRIO_PROTO((trio_pointer_t ref)); /* + */
|
||||
void trio_set_sign TRIO_PROTO((trio_pointer_t ref, int is_showsign));
|
||||
int trio_get_quote TRIO_PROTO((trio_pointer_t ref)); /* ' */
|
||||
void trio_set_quote TRIO_PROTO((trio_pointer_t ref, int is_quote));
|
||||
int trio_get_upper TRIO_PROTO((trio_pointer_t ref));
|
||||
void trio_set_upper TRIO_PROTO((trio_pointer_t ref, int is_upper));
|
||||
#if TRIO_C99
|
||||
int trio_get_largest TRIO_PROTO((trio_pointer_t ref)); /* j */
|
||||
void trio_set_largest TRIO_PROTO((trio_pointer_t ref, int is_largest));
|
||||
int trio_get_ptrdiff TRIO_PROTO((trio_pointer_t ref)); /* t */
|
||||
void trio_set_ptrdiff TRIO_PROTO((trio_pointer_t ref, int is_ptrdiff));
|
||||
int trio_get_size TRIO_PROTO((trio_pointer_t ref)); /* z / Z */
|
||||
void trio_set_size TRIO_PROTO((trio_pointer_t ref, int is_size));
|
||||
#endif
|
||||
|
||||
/* Printing */
|
||||
int trio_print_ref TRIO_PROTO((trio_pointer_t ref, const char *format, ...));
|
||||
int trio_vprint_ref TRIO_PROTO((trio_pointer_t ref, const char *format, va_list args));
|
||||
int trio_printv_ref TRIO_PROTO((trio_pointer_t ref, const char *format, trio_pointer_t *args));
|
||||
|
||||
void trio_print_int TRIO_PROTO((trio_pointer_t ref, int number));
|
||||
void trio_print_uint TRIO_PROTO((trio_pointer_t ref, unsigned int number));
|
||||
/* void trio_print_long TRIO_PROTO((trio_pointer_t ref, long number)); */
|
||||
/* void trio_print_ulong TRIO_PROTO((trio_pointer_t ref, unsigned long number)); */
|
||||
void trio_print_double TRIO_PROTO((trio_pointer_t ref, double number));
|
||||
void trio_print_string TRIO_PROTO((trio_pointer_t ref, char *string));
|
||||
void trio_print_pointer TRIO_PROTO((trio_pointer_t ref, trio_pointer_t pointer));
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* TRIO_TRIOP_H */
|
2024
glib/trio/triostr.c
Normal file
2024
glib/trio/triostr.c
Normal file
File diff suppressed because it is too large
Load Diff
127
glib/trio/triostr.h
Normal file
127
glib/trio/triostr.h
Normal file
@ -0,0 +1,127 @@
|
||||
/*************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2001 Bjorn Reese and Daniel Stenberg.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
|
||||
* CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
#ifndef TRIO_TRIOSTR_H
|
||||
#define TRIO_TRIOSTR_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "triodef.h"
|
||||
#include "triop.h"
|
||||
|
||||
enum {
|
||||
TRIO_HASH_NONE = 0,
|
||||
TRIO_HASH_PLAIN,
|
||||
TRIO_HASH_TWOSIGNED
|
||||
};
|
||||
|
||||
#if !defined(TRIO_STRING_PUBLIC)
|
||||
# if !defined(TRIO_PUBLIC)
|
||||
# define TRIO_PUBLIC
|
||||
# endif
|
||||
# define TRIO_STRING_PUBLIC TRIO_PUBLIC
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
* String functions
|
||||
*/
|
||||
|
||||
TRIO_STRING_PUBLIC int trio_append TRIO_PROTO((char *target, const char *source));
|
||||
TRIO_STRING_PUBLIC int trio_append_max TRIO_PROTO((char *target, size_t max, const char *source));
|
||||
TRIO_STRING_PUBLIC int trio_contains TRIO_PROTO((const char *string, const char *substring));
|
||||
TRIO_STRING_PUBLIC int trio_copy TRIO_PROTO((char *target, const char *source));
|
||||
TRIO_STRING_PUBLIC int trio_copy_max TRIO_PROTO((char *target, size_t max, const char *source));
|
||||
TRIO_STRING_PUBLIC char *trio_create TRIO_PROTO((size_t size));
|
||||
TRIO_STRING_PUBLIC void trio_destroy TRIO_PROTO((char *string));
|
||||
TRIO_STRING_PUBLIC char *trio_duplicate TRIO_PROTO((const char *source));
|
||||
TRIO_STRING_PUBLIC char *trio_duplicate_max TRIO_PROTO((const char *source, size_t max));
|
||||
TRIO_STRING_PUBLIC int trio_equal TRIO_PROTO((const char *first, const char *second));
|
||||
TRIO_STRING_PUBLIC int trio_equal_case TRIO_PROTO((const char *first, const char *second));
|
||||
TRIO_STRING_PUBLIC int trio_equal_case_max TRIO_PROTO((const char *first, size_t max, const char *second));
|
||||
TRIO_STRING_PUBLIC int trio_equal_locale TRIO_PROTO((const char *first, const char *second));
|
||||
TRIO_STRING_PUBLIC int trio_equal_max TRIO_PROTO((const char *first, size_t max, const char *second));
|
||||
TRIO_STRING_PUBLIC TRIO_CONST char *trio_error TRIO_PROTO((int));
|
||||
TRIO_STRING_PUBLIC size_t trio_format_date_max TRIO_PROTO((char *target, size_t max, const char *format, const struct tm *datetime));
|
||||
TRIO_STRING_PUBLIC unsigned long trio_hash TRIO_PROTO((const char *string, int type));
|
||||
TRIO_STRING_PUBLIC char *trio_index TRIO_PROTO((const char *string, int character));
|
||||
TRIO_STRING_PUBLIC char *trio_index_last TRIO_PROTO((const char *string, int character));
|
||||
TRIO_STRING_PUBLIC size_t trio_length TRIO_PROTO((const char *string));
|
||||
TRIO_STRING_PUBLIC int trio_lower TRIO_PROTO((char *target));
|
||||
TRIO_STRING_PUBLIC int trio_match TRIO_PROTO((const char *string, const char *pattern));
|
||||
TRIO_STRING_PUBLIC int trio_match_case TRIO_PROTO((const char *string, const char *pattern));
|
||||
TRIO_STRING_PUBLIC size_t trio_span_function TRIO_PROTO((char *target, const char *source, int (*Function) TRIO_PROTO((int))));
|
||||
TRIO_STRING_PUBLIC char *trio_substring TRIO_PROTO((const char *string, const char *substring));
|
||||
TRIO_STRING_PUBLIC char *trio_substring_max TRIO_PROTO((const char *string, size_t max, const char *substring));
|
||||
TRIO_STRING_PUBLIC double trio_to_double TRIO_PROTO((const char *source, char **endp));
|
||||
TRIO_STRING_PUBLIC float trio_to_float TRIO_PROTO((const char *source, char **endp));
|
||||
TRIO_STRING_PUBLIC trio_long_double_t trio_to_long_double TRIO_PROTO((const char *source, char **endp));
|
||||
TRIO_STRING_PUBLIC long trio_to_long TRIO_PROTO((const char *source, char **endp, int base));
|
||||
TRIO_STRING_PUBLIC unsigned long trio_to_unsigned_long TRIO_PROTO((const char *source, char **endp, int base));
|
||||
TRIO_STRING_PUBLIC char *trio_tokenize TRIO_PROTO((char *string, const char *delimiters));
|
||||
TRIO_STRING_PUBLIC int trio_upper TRIO_PROTO((char *target));
|
||||
|
||||
/*************************************************************************
|
||||
* Dynamic string functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* Opaque type for dynamic strings
|
||||
*/
|
||||
typedef struct _trio_string_t trio_string_t;
|
||||
|
||||
TRIO_STRING_PUBLIC trio_string_t *trio_string_create TRIO_PROTO((int initial_size));
|
||||
TRIO_STRING_PUBLIC void trio_string_destroy TRIO_PROTO((trio_string_t *self));
|
||||
TRIO_STRING_PUBLIC char *trio_string_get TRIO_PROTO((trio_string_t *self, int offset));
|
||||
TRIO_STRING_PUBLIC void trio_xstring_set TRIO_PROTO((trio_string_t *self, char *buffer));
|
||||
TRIO_STRING_PUBLIC char *trio_string_extract TRIO_PROTO((trio_string_t *self));
|
||||
TRIO_STRING_PUBLIC int trio_string_size TRIO_PROTO((trio_string_t *self));
|
||||
TRIO_STRING_PUBLIC void trio_string_terminate TRIO_PROTO((trio_string_t *self));
|
||||
|
||||
TRIO_STRING_PUBLIC int trio_string_append TRIO_PROTO((trio_string_t *self, trio_string_t *other));
|
||||
TRIO_STRING_PUBLIC int trio_string_contains TRIO_PROTO((trio_string_t *self, trio_string_t *other));
|
||||
TRIO_STRING_PUBLIC int trio_string_copy TRIO_PROTO((trio_string_t *self, trio_string_t *other));
|
||||
TRIO_STRING_PUBLIC trio_string_t *trio_string_duplicate TRIO_PROTO((trio_string_t *other));
|
||||
TRIO_STRING_PUBLIC int trio_string_equal TRIO_PROTO((trio_string_t *self, trio_string_t *other));
|
||||
TRIO_STRING_PUBLIC int trio_string_equal_max TRIO_PROTO((trio_string_t *self, size_t max, trio_string_t *second));
|
||||
TRIO_STRING_PUBLIC int trio_string_equal_case TRIO_PROTO((trio_string_t *self, trio_string_t *other));
|
||||
TRIO_STRING_PUBLIC int trio_string_equal_case_max TRIO_PROTO((trio_string_t *self, size_t max, trio_string_t *other));
|
||||
TRIO_STRING_PUBLIC size_t trio_string_format_date_max TRIO_PROTO((trio_string_t *self, size_t max, const char *format, const struct tm *datetime));
|
||||
TRIO_STRING_PUBLIC char *trio_string_index TRIO_PROTO((trio_string_t *self, int character));
|
||||
TRIO_STRING_PUBLIC char *trio_string_index_last TRIO_PROTO((trio_string_t *self, int character));
|
||||
TRIO_STRING_PUBLIC int trio_string_length TRIO_PROTO((trio_string_t *self));
|
||||
TRIO_STRING_PUBLIC int trio_string_lower TRIO_PROTO((trio_string_t *self));
|
||||
TRIO_STRING_PUBLIC int trio_string_match TRIO_PROTO((trio_string_t *self, trio_string_t *other));
|
||||
TRIO_STRING_PUBLIC int trio_string_match_case TRIO_PROTO((trio_string_t *self, trio_string_t *other));
|
||||
TRIO_STRING_PUBLIC char *trio_string_substring TRIO_PROTO((trio_string_t *self, trio_string_t *other));
|
||||
TRIO_STRING_PUBLIC int trio_string_upper TRIO_PROTO((trio_string_t *self));
|
||||
|
||||
TRIO_STRING_PUBLIC int trio_xstring_append_char TRIO_PROTO((trio_string_t *self, char character));
|
||||
TRIO_STRING_PUBLIC int trio_xstring_append TRIO_PROTO((trio_string_t *self, const char *other));
|
||||
TRIO_STRING_PUBLIC int trio_xstring_contains TRIO_PROTO((trio_string_t *self, const char *other));
|
||||
TRIO_STRING_PUBLIC int trio_xstring_copy TRIO_PROTO((trio_string_t *self, const char *other));
|
||||
TRIO_STRING_PUBLIC trio_string_t *trio_xstring_duplicate TRIO_PROTO((const char *other));
|
||||
TRIO_STRING_PUBLIC int trio_xstring_equal TRIO_PROTO((trio_string_t *self, const char *other));
|
||||
TRIO_STRING_PUBLIC int trio_xstring_equal_max TRIO_PROTO((trio_string_t *self, size_t max, const char *other));
|
||||
TRIO_STRING_PUBLIC int trio_xstring_equal_case TRIO_PROTO((trio_string_t *self, const char *other));
|
||||
TRIO_STRING_PUBLIC int trio_xstring_equal_case_max TRIO_PROTO((trio_string_t *self, size_t max, const char *other));
|
||||
TRIO_STRING_PUBLIC int trio_xstring_match TRIO_PROTO((trio_string_t *self, const char *other));
|
||||
TRIO_STRING_PUBLIC int trio_xstring_match_case TRIO_PROTO((trio_string_t *self, const char *other));
|
||||
TRIO_STRING_PUBLIC char *trio_xstring_substring TRIO_PROTO((trio_string_t *self, const char *other));
|
||||
|
||||
#endif /* TRIO_TRIOSTR_H */
|
Loading…
Reference in New Issue
Block a user