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:
Matthias Clasen 2002-11-21 00:35:15 +00:00
parent dc645ce354
commit bc54ea6edf
33 changed files with 11455 additions and 561 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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>&lt;glib/gprintf.h&gt;</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 ##### -->

View File

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

View File

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

View File

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

View File

@ -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
View 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
View 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
View 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__ */

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

216
glib/trio/trio.h Normal file
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

127
glib/trio/triostr.h Normal file
View 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 */