aboutsummaryrefslogtreecommitdiffstats
path: root/trio
diff options
context:
space:
mode:
Diffstat (limited to 'trio')
-rw-r--r--trio/CHANGES626
-rw-r--r--trio/FILES33
-rw-r--r--trio/Makefile61
-rw-r--r--trio/Makefile.in60
-rw-r--r--trio/README38
-rw-r--r--trio/autogen.sh3
-rw-r--r--trio/compare.c53
-rw-r--r--trio/config.cache22
-rw-r--r--trio/config.log52
-rwxr-xr-xtrio/config.status160
-rwxr-xr-xtrio/configure1213
-rw-r--r--trio/configure.in45
-rw-r--r--trio/doc/doc.h161
-rw-r--r--trio/doc/doc_dynamic.h31
-rw-r--r--trio/doc/doc_printf.h532
-rw-r--r--trio/doc/doc_register.h357
-rw-r--r--trio/doc/doc_scanf.h120
-rw-r--r--trio/doc/doc_static.h61
-rw-r--r--trio/doc/footer.html4
-rw-r--r--trio/doc/header.html8
-rw-r--r--trio/doc/trio.cfg873
-rw-r--r--trio/doc/trio.css35
-rw-r--r--trio/example.c594
-rw-r--r--trio/html/group___dynamic_strings.html362
-rw-r--r--trio/html/group___printf.html1259
-rw-r--r--trio/html/group___scanf.html145
-rw-r--r--trio/html/group___special_quantities.html390
-rw-r--r--trio/html/group___static_strings.html1809
-rw-r--r--trio/html/group___user_defined.html379
-rw-r--r--trio/html/index.html88
-rw-r--r--trio/html/modules.html23
-rw-r--r--trio/html/trio.css35
-rwxr-xr-xtrio/install-sh250
-rw-r--r--trio/libtrio.abin0 -> 169062 bytes
-rwxr-xr-xtrio/maketgz46
-rwxr-xr-xtrio/regressionbin0 -> 166737 bytes
-rw-r--r--trio/regression.c1206
-rw-r--r--trio/strio.h73
-rw-r--r--trio/trio.c6855
-rw-r--r--trio/trio.h216
-rw-r--r--trio/triodef.h220
-rw-r--r--trio/trionan.c901
-rw-r--r--trio/trionan.h81
-rw-r--r--trio/triop.h150
-rw-r--r--trio/triostr.c2102
-rw-r--r--trio/triostr.h140
46 files changed, 21872 insertions, 0 deletions
diff --git a/trio/CHANGES b/trio/CHANGES
new file mode 100644
index 00000000..4fe3aa80
--- /dev/null
+++ b/trio/CHANGES
@@ -0,0 +1,626 @@
+CHANGES -- trio
+
+
+The changes listed without a name attributed to them were most likely done by
+Bjorn Reese and/or Daniel Stenberg.
+
+Version 1.10 - 2003/03/06
+-------------------------
+* Rearranged some include files to accommodate large file support (reported by
+ Albert Chin-A-Young)
+
+* Added support for SunOS 4.1.x lack of strerror, tolower, and toupper
+ (reported by Peter McCluskey).
+
+* Fixed pedantic compilation with TRIO_MINIMAL.
+
+* Jose Kahan
+ Moved <limits.h> to avoid redefinition problems.
+
+* Fixed hex-float exponents (reported by Matthias Clasen).
+
+* Fixed handling of negative width and precision via paramters (reported by
+ Jacob Navia).
+
+* Nigel Hall
+ Fixed TRIO_VA_START for VMS.
+
+* Rune Enggaard Lausen
+ Fixed compilation for Borland C++ Builder.
+
+* Fixed precision of hex-float numbers (reported by James Antill).
+
+* Fixed plus sign only to be added for signed numbers.
+
+* Fixed printing of integers with value and precision of zero (reported by
+ James Antill).
+
+* Fixed %#.o to only print one zero if the value is zero (reported by James
+ Antill).
+
+* Rewrote check for IEEE compilation option to remove dependency on additional
+ scripts.
+
+* Mehdi Lavasani
+ Makefile install target fixed to work with older install programs.
+
+* Collapsed the DECC, MSVC, HP-UX, and AIX code for trio_fpclassify_and_sign()
+ with further preprocessing.
+
+
+Version 1.9 - 2002/10/13
+------------------------
+* Fixed trio_fpclassify_and_signbit on AIX 3.2
+
+* Added configure check for -ieee/-mieee compilation option for Alpha machines.
+
+* Craig Berry
+ Fixed compilation on VMS.
+
+* Albert Chin-A-Young
+ Fixed incorrect conditional expression in trio_isinf.
+
+* Fixed the warnings about uninitialized va_list in the printfv and scanfv
+ family without the use of compiler specific pragmas (suggested by Ian
+ Pilcher).
+
+* Fixed space flag for floating-point numbers (reported by Ian Main).
+
+
+Version 1.8 - 2002/07/10
+------------------------
+* Fixed infinite loop in multibyte handling (reported by Gisli Ottarsson).
+
+* Added the customizable cprintf/cscanf family which enables to user to specify
+ input and output stream functions (suggested by Florian Schulze).
+
+* Fixed trio_isinf by removing the HP-UX workaround, and instead making sure
+ that the C99 macro will adhere to the trio return values (reported by Luke
+ Dunstan).
+
+* Alexander Lukyanov
+ Fixed boundary case for scanning and EOF.
+
+* Jacob Navia
+ Enabled the L modifier for formatting.
+
+* Added TRIO_MINIMAL to build trio without the string functions.
+
+* Added the R modifier to print rounded floating-point numbers.
+
+* Added trio_to_long_double and long double scanning (the L modifier).
+
+* Added trio_locale_decimal_point, trio_locale_thousand_separator,
+ trio_locale_grouping to overwrite locale settings.
+
+* Rewrote TrioWriteDouble to avoid temporary buffers and thus the danger of
+ buffer overflows (for instance %.5000f).
+
+* Improved floating-point formatting accuracy.
+
+* Fixed formatting of non-decimal exponents.
+
+* Fixed thousand separator checking.
+
+* Fixed %f scanning to get a float and %lf to get a double.
+
+* Fixed WIN32 compilation (reported by Emmanuel Mogenet)
+
+* Fixed regression test cases to exclude disabled features.
+
+
+Version 1.7 - 2002/05/07
+------------------------
+* Fixed trio_to_double to handle hex-floats properly.
+
+* Fixed printing of %a-format to be like %e, not like %g.
+
+* Fixed floating-point printing of values beyond the machine accuracy.
+
+* Fixed %f for printing with large precision.
+
+* Fixed the usage of C99 nan(), which caused a crash on OSF/1 (reported by
+ Georg Bolz)
+
+* Joe Orton
+ Fixed %p on 64-bit platforms.
+
+* Made trio compile with K&R compilers.
+
+* Emmanuel Mogenet
+ Fixed bug in trio_asprintf.
+
+* Emmanuel Mogenet
+ Various WIN32 fixes.
+
+* Joe Orton
+ Fixed trio_isinf() on HP-UX, and added test cases.
+
+* Joe Orton
+ Fixed non-portable use of $^ in Makefile.
+
+* Joe Orton
+ Added autoconf.
+
+* Alexander Lukyanov
+ Fixed a number of bugs in the scanning of EOF and the count specifier.
+
+* Richard Jinks
+ Added trio_nzero
+
+* Fixed incorrect handling of return code from TrioReadChar (reported by
+ Henrik Löf)
+
+* Fixed parsing of character class expressions.
+
+* Fixed trio_to_double which did not work with long fractions.
+
+* Fixed %f for printing of large numbers.
+
+* Fixed %#s to handle whitespaces as non-printable characters.
+
+* Added trio_isfinite, trio_signbit, and trio_fpclassify.
+
+* Added new test cases.
+
+
+Version 1.6 - 2002/01/13
+------------------------
+* Added dynamic string functions.
+
+* Rewrote and extended documentation in JavaDoc (using Doxygen).
+
+* Moved and renamed strio functions to triostr.
+
+* Robert Collins
+ Added definition for Cygwin.
+
+* Markus Henke
+ Added long double workaround for the HP C/iX compiler.
+
+* Marc Verwerft
+ Improved error handling for dynamically allocated strings.
+
+* John Fotheringham
+ Made trionan compile on OpenVMS.
+
+* Added 'd' and 'D' as exponent letters when using TRIO_MICROSOFT.
+
+* Fixed uninitial memory read for the parameter modifiers.
+
+
+Version 1.5 - 2001/09/08
+------------------------
+* Merged with libxml changes.
+
+* Moved NaN and Inf handling to separate file to enable reuse in other
+ projects.
+
+* Igor Zlatkovic
+ Fixed TrioGenerateNan for MSVC.
+
+* Fixed lots of preprocessor macros and internal data structure names.
+
+
+Version 1.4 - 2001/06/03
+------------------------
+* Added hex-float (%a and %A) for scanning.
+
+* Added wide character arguments (%ls, %ws, %S, %lc, %wc, and %C) for both
+ printf and scanf.
+
+* Added mutex callbacks for user-specified specifiers to enable applications to
+ add thread-safety. These are registered with trio_register, where the
+ namespace is set to either ":enter" to lock a mutex, or ":leave" to unlock a
+ mutex.
+
+* Added equivalence class expressions for scanning. For example, %[[=a=]] scans
+ for all letters in the same equivalence class as the letter 'a' as defined
+ by the locale.
+
+* Changed character class expressions for scanning. The expressions must now
+ be embedded withing an extra set of brackets, e.g. %[[:alpha:]]. This was
+ done to adhere to the syntax of UNIX98 regular expressions.
+
+* Added the possibility to specify standard support (TRIO_C99 etc.) as compiler
+ options.
+
+* Fixed conversion of hex-float in StrToDouble.
+
+* Fixed formatting of hex-float numbers.
+
+* Stan Boehm
+ Fixed crash on QNX, which happend because some buffers on the stack were too
+ big.
+
+* Fixed default precision for %f and %g (reported by Jose Ortiz)
+
+* Howard Kapustein
+ Added the I8, I16, I32, and I64 modifiers.
+
+* Jose Ortiz
+ Fixed rounding problem for %e.
+
+* Jose Ortiz
+ Fixed various problems with the xlC and Sun C++ compilers.
+
+
+Version 1.3 - 2001/05/16
+------------------------
+* trio's treatment of the field width when the %e code was used was not
+ correct (reported by Gisli Ottarsson). It turns out the fraction part should
+ be zero-padded by default and the exponent part should be zero-prefixed if
+ it is only one digit. At least that's how the GNU and Sun libc's work. The
+ trio floating point output looks identical to them now.
+
+* Fixed group scanning with modifiers.
+
+* Fixed compilation for 64-bit Digital Unix.
+
+* Igor Zlatkovic
+ Fixed compilation of dprintf, which uses read/write, for MSVC.
+
+* Fixed various compilation problems on Digital Unix (mainly associated with
+ va_list).
+
+
+Version 1.2 - 2001/04/11
+------------------------
+* Added autoconf integration. If compiled with HAVE_CONFIG_H the following
+ happens. Firstly, <config.h> is included. Secondly, trio will only be
+ compiled if WITH_TRIO is defined herein. Thirdly, if TRIO_REPLACE_STDIO is
+ defined, only stdio functions that have not been detected by autoconf, i.e.
+ those not defined by HAVE_PRINTF or similar, will be replaced by trio
+ functions (suggested by Daniel Veillard).
+
+* Fixed '%m.nf' output. Previously trio did not treat the width properly
+ in all cases (reported by Gisli Ottarsson).
+
+* Added explicit promotion for the scanfv family.
+
+* Fixed more C++ compilation warnings.
+
+
+Version 1.1 - 2001/02/25
+------------------------
+* Added explicit promotion for the printfv familiy. A float must be specified
+ by %hf.
+
+* Fixed positionals for printfv (reported by Gisli Ottarsson).
+
+* Fixed an integer to pointer conversion problem on the SGI MIPS C compiler
+ (reported by Gisli Ottarsson).
+
+* Fixed ANSI C++ warnings (type casting, and namespace is a reserved keyword).
+
+* Added \n to all examples in the documentation to prevent confusion.
+
+* Fixed StrSubstringMax
+
+
+Version 1.0 - 2000/12/10
+------------------------
+* Bumped Version number.
+
+
+Version 0.25 - 2000/12/09
+-------------------------
+* Wrote more documentation.
+
+* Improved NaN support and added NaN to regression test.
+
+* Fixed C99 support.
+
+* Added missing getter/setter functions.
+
+
+Version 0.24 - 2000/12/02
+-------------------------
+* Added callback functionality for the user-defined specifier (<>). All
+ the necessary functions are defined in triop.h header file. See the
+ documentation for trio_register for further detail.
+
+* Wrote initial documentation on the callback functionality.
+
+* Added the printfv and scanfv family of functions, which takes a pointer
+ array rather than variadic arguments. Each pointer in the array must point
+ to the associated data (requested by Bruce Korb).
+
+* As indicated in version 0.21 the extension modifiers (<>) have now been
+ completely removed.
+
+* Added skipping of thousand-separators in floating-point number scanning.
+
+
+Version 0.23 - 2000/10/21
+-------------------------
+* Added width to scanning of floating-point numbers.
+
+* Wrote more documentation on trio_printf.
+
+* Fixed problem with trailing zeroes after decimal-point.
+
+
+Version 0.22 - 2000/08/06
+-------------------------
+* Added LC_CTYPE locale dependent character class expressions to scan lists.
+ Included are [:alnum:], [:alpha:], [:cntrl:], [:digit:], [:graph:],
+ [:lower:], [:print:], [:punct:], [:space:], [:upper:], [:xdigit:]
+
+* Added C escapes to alternative string formatting and scanning.
+
+* Added StrSubstringMax.
+
+* Wrote a little more documentation.
+
+* Fixed scanf return values.
+
+* Fixed a sign error for non-ascii characters.
+
+
+Version 0.21 - 2000/07/19
+-------------------------
+* Converted the documentation to TeX. With latex2man the documentation can
+ automatically be converted into man pages.
+
+* Added trio_scanf, trio_vscanf, trio_fscanf, and trio_vfscanf.
+
+* Added trio_dprintf, trio_vdprintf, trio_dscanf, and trio_vdscanf. These
+ functions can be used to write and read directly to pipes and sockets (the
+ assume blocking sockets). Stdio buffering is surpassed, so the functions are
+ async-safe. However, reading from stdin (STDIN_FILENO) or writing to stdout
+ (STDOUT_FILENO) reintroduces the buffering.
+
+* Added trio_dprintf and trio_vdprintf. These can be used to write directly
+ to pipes and sockets.
+
+* Paul Janzen
+ Added trio_asprintf and trio_vasprintf, which are compatible with the GNU
+ and BSD interfaces.
+
+* Added scanlist ranges for group scanning (%[]).
+
+* Added width for scanning (missing for floating-point numbers though).
+
+* Added variable size modifier (&) to handle system defined types of unknown
+ size. This modifier makes certain assumptions about the integer sizes, which
+ may not be valid on any machine. Consequently, the modifier will remain
+ undocumented, as it may be removed later.
+
+* Added \777 and \xFF to alternative string scanning (%#s)
+
+* Added the TRIO_REPLACE_STDIO check in the header.
+
+* Improved performance of the multibyte character parsing.
+
+* Fixed positionals (%n$) which had stopped working.
+
+* Fixed hh and ll modifiers to allow exactly two letters and no more.
+
+* Fixed ANSI C++ warnings. Also fixed the compiler warning about casting
+ between integer and pointer (this has been annoying me for ages).
+
+* Fixed snprintf and vsnprintf with zero buffer size.
+
+* Fixed NAN problems (reported by Keith Briggs).
+
+* Fixed parsing of multibyte characters. The format string was not correctly
+ advanced in case of a multibyte character.
+
+* Renamed many of the internal functions to have more consistant names.
+
+* Removed the <quote=c> and <fill=c> modifiers. They are not really worth
+ including. The other <> modifiers may disappear as well.
+
+
+Version 0.20 - 2000/06/05
+-------------------------
+* Added intmax_t and ptrdiff_t support.
+
+* Added support for LC_NUMERIC grouping.
+
+* Added double-dot notation for the conversion base. The style is now
+ %width.precision.base, where any argument can be a number, an asterix
+ indicating a parameter, or be omitted entirely. For example, %*..2i is
+ to specify binary numbers without precision, and with width as a parameter
+ on the va_list.
+
+* Added sticky modifier (!), which makes subsequent specifiers of the same
+ type reuse the current modifiers. Inspired by a suggestion from Gary Porter.
+
+* Added group scanning (%[]). Scanlist ranges and multibyte sequences are not
+ supported yet.
+
+* Added count scanning (%n).
+
+* Changed the number scanning to accept thousand separators and any base.
+
+* Fixed positional for parameters. It is possible to write something like
+ %3$*1$.*2$d (which happens to be the same as %*.*d).
+
+* Fixed precision of integers.
+
+* Fixed parameter flags. Before trio could only handle one parameter flag per
+ specifier, although two (three with double-dot base) were possible.
+
+* Fixed isinf() for those platforms where it is unimplemented.
+
+
+Version 0.18 - 2000/05/27
+-------------------------
+* Rewrote the entire floating-point formatting function (Danny Dulai had
+ reported several errors and even supplied some patches, which unfortunately
+ were lost due to the refactoring).
+
+* Removed the use of strlen() in the declaration of a stack array. This
+ caused problems on some compilers (besides it isn't really ANSI C compliant
+ anyways). Using some arbitrarily chosen maximum value; should examine if
+ some standard defines an upper limit on the length of decimal-point and
+ thousands-separator (sizeof(wchar_t) perhaps?)
+
+* Changed the parsing of the format string to be multibyte aware.
+
+
+Version 0.17 - 2000/05/19
+-------------------------
+* Added INF, -INF, and NAN for floating-point numbers.
+
+* Fixed %#.9g -- alternative with precision.
+
+* Ken Gibson
+ Fixed printing of negative hex numbers
+
+* Joerg (last name unknown)
+ Fixed convertion of non-ASCII characters
+
+
+Version 0.16 - 1999/08/06
+-------------------------
+* Changed the constness of the second argument of StrFloat and StrDouble. The
+ lack of parameter overloading in C is the reason for the strange use of
+ constness in strtof and strtod.
+
+* Cleaned up constness.
+
+
+Version 0.15 - 1999/07/23
+-------------------------
+* Fixed the internal representation of numbers from signed to unsigned. Signed
+ numbers posed a problem for large unsigned numbers (reported by Tero)
+
+* Fixed a tiny bug in trio_vsprintfcat
+
+* Changed the meaning of the max argument of StrAppendMax to be consistant
+ with StrFormatAppendMax. Now it is the maximal size of the entire target
+ buffer, not just the appended size. This makes it easier to avoid buffer
+ overflows (requested by Tero)
+
+
+Version 0.14 - 1999/05/16
+-------------------------
+* Added size_t support (just waiting for a C99 compliant compiler to add
+ ptrdiff_t and intmax_t)
+
+* Rewrote TrioOutStreamDouble so it does not use the libc sprintf to emulate
+ floating-point anylonger.
+
+* Fixed width, precision, and adjustment for numbers and doubles.
+
+
+Version 0.13 - 1999/05/06
+-------------------------
+* Fixed zero padding for %d. Now %d will only zero pad if explicitly requested
+ to do so with the 0 flag (reported by Tero).
+
+* Fixed an incorrect while() condition in TrioGetString (reported by Tero).
+
+
+Version 0.12 - 1999/04/19
+-------------------------
+* Fixed incorrect zero padding of pointers
+
+* Added StrHash with STRIO_HASH_PLAIN
+
+* Added StrFormatDateMax
+
+
+Version 0.11 - 1999/03/25
+-------------------------
+* Made it compile under cygwin
+
+* Fixed a bug were TrioPreprocess would return an error if no formatting chars
+ were found (reported by Tero).
+
+
+Version - 1999/03/19
+--------------------
+* Added trio_strerror and TRIO_ERROR_NAME.
+
+* Changed the error codes to be positive (as errno)
+
+* Fixed two reads of uninitialized memory reported by Purify
+
+* Added binary specifiers 'b' and 'B' (like SCO.) ThousandSeparator can be
+ used to separate nibbles (4 bit)
+
+* Renamed all Internal* functions to Trio*, which seems like a better
+ namespace (even though it is of no practical interest because these
+ functions are not visible beyond the scope of this file.)
+
+
+Version - 1999/03/12
+--------------------
+* Added hex-float format for StrToDouble
+
+* Double references and gaps in the arguments are not allowed (for the %n$
+ format) and in both cases an error code is returned.
+
+* Added StrToDouble (and StrToFloat)
+
+
+Version - 1999/03/08
+--------------------
+* Added InStream and OutStream to the trio_T structure.
+
+* Started work on TrioScan.
+
+* Return values for errors changed. Two macros to unpack the error code has
+ been added to the header.
+
+* Shortshort (hh) flag added.
+
+* %#s also quotes the quote-char now.
+
+* Removed the 'errorInFormat' boolean, which isn't used anymore after the
+ functions bail out with an error instead.
+
+
+Version - 1999/03/04
+--------------------
+* More than MAX_PARAMETERS parametes will now cause the TrioPreprocess()
+ function to return error.
+
+* Unknown flags and/or specifiers cause errors too.
+
+* Added trio_snprintfcat and trio_vsnprintfcat and the defined name
+ StrFormatAppendMax. They append a formatted string to the end of a string.
+
+* Define MAX_PARAMETERS to 128 at all times instead of using NL_ARGMAX when
+ that exists.
+
+* Added platform fixes for Amiga as suggested by Tero Jänkä <tesaja@utu.fi>
+
+
+Version - 1999/01/31
+--------------------
+* vaprintf did add a zero byte even when it had failed.
+
+* Cleaned up the code for locale handling and thousand separator
+
+* Added trio_aprintf() and trio_vaprintf(). They return an allocated string.
+
+* Added thousands separator for numbers
+
+* Added floating point support for *printf
+
+
+Version - 1998/10/20
+--------------------
+* StrMatchCase() called StrMatch() instead of itself recursively
+
+* Rewrote the implementation of *printf and *scanf and put all the code in
+ this file. Extended qualifiers and qualifiers from other standards were
+ added.
+
+* Added StrSpanFunction, StrToLong, and StrToUnsignedLong
+
+
+Version - 1998/05/23
+--------------------
+* Made the StrEqual* functions resistant to NULL pointers
+
+* Turns out strdup() is no standard at all, and some platforms (I seem to
+ recall HP-UX) has problems with it. Made our own StrDuplicate() instead.
+
+* Added StrFormat() and StrFormatMax() to serve as sprintf() and snprintf()
+ respectively.
diff --git a/trio/FILES b/trio/FILES
new file mode 100644
index 00000000..22a5ea12
--- /dev/null
+++ b/trio/FILES
@@ -0,0 +1,33 @@
+FILES
+README
+CHANGES
+Makefile.in
+maketgz
+strio.h
+trio.c
+trio.h
+triodef.h
+trionan.c
+trionan.h
+triop.h
+triostr.c
+triostr.h
+compare.c
+example.c
+regression.c
+configure
+configure.in
+install-sh
+autogen.sh
+doc/doc.h
+doc/doc_dynamic.h
+doc/doc_printf.h
+doc/doc_register.h
+doc/doc_scanf.h
+doc/doc_static.h
+doc/footer.html
+doc/header.html
+doc/trio.cfg
+doc/trio.css
+html/trio.css
+html/*.html
diff --git a/trio/Makefile b/trio/Makefile
new file mode 100644
index 00000000..84e78fd0
--- /dev/null
+++ b/trio/Makefile
@@ -0,0 +1,61 @@
+# Generated automatically from Makefile.in by configure.
+CC = gcc
+CFLAGS = -g -O2 -DDEBUG
+OBJS = triostr.o trio.o trionan.o
+TARGETLIB = libtrio.a
+TARGETINCS = trio.h triop.h triodef.h trionan.h triostr.h
+LDFLAGS = -L. -ltrio -lm
+AR = ar
+RANLIB = ranlib
+ERASE = rm -f
+MKDIR = mkdir -p
+GENDOC = doxygen
+
+PURIFY = purify
+PURIFYOPTIONS = -chain-length=16 -first-only=YES
+
+# Installation settings
+INSTALL = /usr/bin/install -c
+INSTALL_DATA = ${INSTALL} -m 644
+prefix = /usr/local
+exec_prefix = ${prefix}
+includedir = ${prefix}/include
+libdir = ${exec_prefix}/lib
+
+all: $(TARGETLIB) $(TARGET) regression
+
+test:
+ ./regression
+
+install: $(TARGETLIB)
+ $(MKDIR) $(libdir)
+ $(MKDIR) $(includedir)
+ $(INSTALL_DATA) $(TARGETLIB) $(libdir)/$(TARGETLIB)
+ for i in $(TARGET_INCS);do \
+ (set -x;$(INSTALL_DATA) $$i $(includedir)); \
+ done
+
+pure: $(TOBJS) $(OBJS)
+ $(PURIFY) $(PURIFYOPTIONS) $(CC) $(CFLAGS) $^ $(LDFLAGS)
+
+regression: regression.o $(TARGETLIB)
+ $(CC) $(CFLAGS) regression.o $(LDFLAGS) -o $@
+
+example: example.o $(TARGETLIB)
+ $(CC) $(CFLAGS) example.o $(LDFLAGS) -o $@
+
+compare: compare.o $(TARGETLIB)
+ $(CC) $(CFLAGS) compare.o $(LDFLAGS) -o $@
+
+userdef: userdef.o $(TARGETLIB)
+ $(CC) $(CFLAGS) userdef.o $(LDFLAGS) -o $@
+
+$(TARGETLIB): $(OBJS)
+ $(AR) ruv $(TARGETLIB) $(OBJS)
+ $(RANLIB) $(TARGETLIB)
+
+doc::
+ $(GENDOC) doc/trio.cfg
+
+clean:
+ $(ERASE) *~ core regression example $(TOBJS) $(OBJS) $(TARGET) $(TARGETLIB) example.o regression.o
diff --git a/trio/Makefile.in b/trio/Makefile.in
new file mode 100644
index 00000000..7be4bcb1
--- /dev/null
+++ b/trio/Makefile.in
@@ -0,0 +1,60 @@
+CC = @CC@
+CFLAGS = @CFLAGS@ -DDEBUG
+OBJS = triostr.o trio.o trionan.o
+TARGETLIB = libtrio.a
+TARGETINCS = trio.h triop.h triodef.h trionan.h triostr.h
+LDFLAGS = -L. -ltrio -lm
+AR = ar
+RANLIB = @RANLIB@
+ERASE = rm -f
+MKDIR = mkdir -p
+GENDOC = doxygen
+
+PURIFY = purify
+PURIFYOPTIONS = -chain-length=16 -first-only=YES
+
+# Installation settings
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+
+all: $(TARGETLIB) $(TARGET) regression
+
+test:
+ ./regression
+
+install: $(TARGETLIB)
+ $(MKDIR) $(libdir)
+ $(MKDIR) $(includedir)
+ $(INSTALL_DATA) $(TARGETLIB) $(libdir)/$(TARGETLIB)
+ for i in $(TARGET_INCS);do \
+ (set -x;$(INSTALL_DATA) $$i $(includedir)); \
+ done
+
+pure: $(TOBJS) $(OBJS)
+ $(PURIFY) $(PURIFYOPTIONS) $(CC) $(CFLAGS) $^ $(LDFLAGS)
+
+regression: regression.o $(TARGETLIB)
+ $(CC) $(CFLAGS) regression.o $(LDFLAGS) -o $@
+
+example: example.o $(TARGETLIB)
+ $(CC) $(CFLAGS) example.o $(LDFLAGS) -o $@
+
+compare: compare.o $(TARGETLIB)
+ $(CC) $(CFLAGS) compare.o $(LDFLAGS) -o $@
+
+userdef: userdef.o $(TARGETLIB)
+ $(CC) $(CFLAGS) userdef.o $(LDFLAGS) -o $@
+
+$(TARGETLIB): $(OBJS)
+ $(AR) ruv $(TARGETLIB) $(OBJS)
+ $(RANLIB) $(TARGETLIB)
+
+doc::
+ $(GENDOC) doc/trio.cfg
+
+clean:
+ $(ERASE) *~ core regression example $(TOBJS) $(OBJS) $(TARGET) $(TARGETLIB) example.o regression.o
diff --git a/trio/README b/trio/README
new file mode 100644
index 00000000..55ad1b07
--- /dev/null
+++ b/trio/README
@@ -0,0 +1,38 @@
+README -- trio
+
+Trio is a package with portable string functions. Including printf() clones
+and others.
+
+ 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.
+
+Trio is intended to be an integral part of another application, so we
+have not done anything to create a proper installation.
+
+Compile with 'make' (edit the Makefile if you want a release build)
+
+Test the package with 'make test'
+
+Install by copying trio.h, triop.h, and libtrio.a (and man/man?/* if
+you want documentation) to the appropriate directories.
+
+Catch some usage examples in example.c
+
+Send feedback and patches to the mailing list, subscription and other
+information is found here:
+
+ http://lists.sourceforge.net/lists/listinfo/ctrio-talk
+
+Enjoy!
+
+Trio web page
+
+ http://daniel.haxx.se/trio/
diff --git a/trio/autogen.sh b/trio/autogen.sh
new file mode 100644
index 00000000..9299034e
--- /dev/null
+++ b/trio/autogen.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+autoconf
+rm -rf autom4te.cache
diff --git a/trio/compare.c b/trio/compare.c
new file mode 100644
index 00000000..3823aa2d
--- /dev/null
+++ b/trio/compare.c
@@ -0,0 +1,53 @@
+#include "trio.h"
+
+#define compare(format, value) printf("FORMAT: %s\n", format); printf("TRIO: "); trio_printf(format,value); printf("\nLIBC: "); \
+printf(format,value); printf("\n\n");
+
+int main()
+{
+ compare("\"%e\"",2.342E+02);
+ compare("\"%10.4e\"",-2.342E-02);
+ compare("\"%11.4e\"",-2.342E-02);
+ compare("\"%12.4e\"",-2.342E-02);
+ compare("\"%13.4e\"",-2.342E-02);
+ compare("\"%14.4e\"",-2.342E-02);
+ compare("\"%15.4e\"",-2.342E-02);
+ compare("\"%16.4e\"",-2.342E-02);
+ compare("\"%16.4e\"",-2.342E-22);
+ compare("\"%G\"",-2.342E-02);
+ compare("\"%G\"",3.1415e-6);
+ compare("%016e", 3141.5);
+ compare("%16e", 3141.5);
+ compare("%-16e", 3141.5);
+ compare("%010.3e", 3141.5);
+
+ compare("*%5f*", 3.3);
+ compare("*%5f*", 3.0);
+ compare("*%5f*", .999999E-4);
+ compare("*%5f*", .99E-3);
+ compare("*%5f*", 3333.0);
+
+ compare("*%5g*", 3.3);
+ compare("*%5g*", 3.0);
+ compare("*%5g*", .999999E-4);
+ compare("*%5g*", .99E-3);
+ compare("*%5g*", 3333.0);
+ compare("*%5g*", 0.01);
+
+ compare("*%5.g*", 3.3);
+ compare("*%5.g*", 3.0);
+ compare("*%5.g*", .999999E-4);
+ compare("*%5.g*", 1.0E-4);
+ compare("*%5.g*", .99E-3);
+ compare("*%5.g*", 3333.0);
+ compare("*%5.g*", 0.01);
+
+ compare("*%5.2g*", 3.3);
+ compare("*%5.2g*", 3.0);
+ compare("*%5.2g*", .999999E-4);
+ compare("*%5.2g*", .99E-3);
+ compare("*%5.2g*", 3333.0);
+ compare("*%5.2g*", 0.01);
+
+ return 0;
+}
diff --git a/trio/config.cache b/trio/config.cache
new file mode 100644
index 00000000..a12b1195
--- /dev/null
+++ b/trio/config.cache
@@ -0,0 +1,22 @@
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+ac_cv_ieee_option=${ac_cv_ieee_option=none}
+ac_cv_path_install=${ac_cv_path_install='/usr/bin/install -c'}
+ac_cv_prog_CC=${ac_cv_prog_CC=gcc}
+ac_cv_prog_RANLIB=${ac_cv_prog_RANLIB=ranlib}
+ac_cv_prog_cc_cross=${ac_cv_prog_cc_cross=no}
+ac_cv_prog_cc_g=${ac_cv_prog_cc_g=yes}
+ac_cv_prog_cc_works=${ac_cv_prog_cc_works=yes}
+ac_cv_prog_gcc=${ac_cv_prog_gcc=yes}
diff --git a/trio/config.log b/trio/config.log
new file mode 100644
index 00000000..5cb4bfeb
--- /dev/null
+++ b/trio/config.log
@@ -0,0 +1,52 @@
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+configure:529: checking for gcc
+configure:642: checking whether the C compiler (gcc ) works
+configure:658: gcc -o conftest conftest.c 1>&5
+configure:684: checking whether the C compiler (gcc ) is a cross-compiler
+configure:689: checking whether we are using GNU C
+configure:698: gcc -E conftest.c
+configure:717: checking whether gcc accepts -g
+configure:788: checking for a BSD compatible install
+configure:843: checking for ranlib
+configure:873: checking for IEEE compilation options
+configure:890: gcc -c -g -O2 conftest.c 1>&5
+configure:884:3: #error "Option needed"
+configure: failed program was:
+#line 879 "configure"
+#include "confdefs.h"
+
+int main() {
+
+#if !(defined(__alpha) && (defined(__DECC) || defined(__DECCXX) || (defined(__osf__) && defined(__LANGUAGE_C__))) && (defined(VMS) || defined(__VMS)))
+# error "Option needed"
+#endif
+
+; return 0; }
+configure:909: gcc -c -g -O2 conftest.c 1>&5
+configure:903:3: #error "Option needed"
+configure: failed program was:
+#line 898 "configure"
+#include "confdefs.h"
+
+int main() {
+
+#if !(defined(__alpha) && (defined(__DECC) || defined(__DECCXX) || (defined(__osf__) && defined(__LANGUAGE_C__))) && !(defined(VMS) || defined(__VMS)) && !defined(_CFE))
+# error "Option needed"
+#endif
+
+; return 0; }
+configure:928: gcc -c -g -O2 conftest.c 1>&5
+configure:922:3: #error "Option needed"
+configure: failed program was:
+#line 917 "configure"
+#include "confdefs.h"
+
+int main() {
+
+#if !(defined(__alpha) && (defined(__GNUC__) && (defined(__osf__) || defined(__linux__))))
+# error "Option needed"
+#endif
+
+; return 0; }
diff --git a/trio/config.status b/trio/config.status
new file mode 100755
index 00000000..4dc54459
--- /dev/null
+++ b/trio/config.status
@@ -0,0 +1,160 @@
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host merlin:
+#
+# ./configure
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: ./config.status [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running ${CONFIG_SHELL-/bin/sh} ./configure --no-create --no-recursion"
+ exec ${CONFIG_SHELL-/bin/sh} ./configure --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "./config.status generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "$ac_cs_usage"; exit 0 ;;
+ *) echo "$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=.
+ac_given_INSTALL="/usr/bin/install -c"
+
+trap 'rm -fr Makefile conftest*; exit 1' 1 2 15
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g$/@g/; /@g$/s/[\\&%]/\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g$/%g/' > conftest.subs <<\CEOF
+/^[ ]*VPATH[ ]*=[^:]*$/d
+
+s%@SHELL@%/bin/sh%g
+s%@CFLAGS@%-g -O2%g
+s%@CPPFLAGS@%%g
+s%@CXXFLAGS@%%g
+s%@FFLAGS@%%g
+s%@DEFS@% %g
+s%@LDFLAGS@%%g
+s%@LIBS@%%g
+s%@exec_prefix@%${prefix}%g
+s%@prefix@%/usr/local%g
+s%@program_transform_name@%s,x,x,%g
+s%@bindir@%${exec_prefix}/bin%g
+s%@sbindir@%${exec_prefix}/sbin%g
+s%@libexecdir@%${exec_prefix}/libexec%g
+s%@datadir@%${prefix}/share%g
+s%@sysconfdir@%${prefix}/etc%g
+s%@sharedstatedir@%${prefix}/com%g
+s%@localstatedir@%${prefix}/var%g
+s%@libdir@%${exec_prefix}/lib%g
+s%@includedir@%${prefix}/include%g
+s%@oldincludedir@%/usr/include%g
+s%@infodir@%${prefix}/info%g
+s%@mandir@%${prefix}/man%g
+s%@CC@%gcc%g
+s%@INSTALL_PROGRAM@%${INSTALL}%g
+s%@INSTALL_SCRIPT@%${INSTALL_PROGRAM}%g
+s%@INSTALL_DATA@%${INSTALL} -m 644%g
+s%@RANLIB@%ranlib%g
+
+CEOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+
+CONFIG_FILES=${CONFIG_FILES-"Makefile"}
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+
+
+exit 0
diff --git a/trio/configure b/trio/configure
new file mode 100755
index 00000000..35ab3503
--- /dev/null
+++ b/trio/configure
@@ -0,0 +1,1213 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.13"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=triodef.h
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:529: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:559: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:610: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:642: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 653 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:658: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:684: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:689: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:698: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:717: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:788: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+# Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:843: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+
+echo $ac_n "checking for IEEE compilation options""... $ac_c" 1>&6
+echo "configure:873: checking for IEEE compilation options" >&5
+if eval "test \"`echo '$''{'ac_cv_ieee_option'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+cat > conftest.$ac_ext <<EOF
+#line 879 "configure"
+#include "confdefs.h"
+
+int main() {
+
+#if !(defined(__alpha) && (defined(__DECC) || defined(__DECCXX) || (defined(__osf__) && defined(__LANGUAGE_C__))) && (defined(VMS) || defined(__VMS)))
+# error "Option needed"
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:890: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_ieee_option="/IEEE_MODE=UNDERFLOW_TO_ZERO/FLOAT=IEEE"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cat > conftest.$ac_ext <<EOF
+#line 898 "configure"
+#include "confdefs.h"
+
+int main() {
+
+#if !(defined(__alpha) && (defined(__DECC) || defined(__DECCXX) || (defined(__osf__) && defined(__LANGUAGE_C__))) && !(defined(VMS) || defined(__VMS)) && !defined(_CFE))
+# error "Option needed"
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:909: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_ieee_option="-ieee"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cat > conftest.$ac_ext <<EOF
+#line 917 "configure"
+#include "confdefs.h"
+
+int main() {
+
+#if !(defined(__alpha) && (defined(__GNUC__) && (defined(__osf__) || defined(__linux__))))
+# error "Option needed"
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:928: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_ieee_option="-mieee"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_ieee_option="none"
+
+fi
+rm -f conftest*
+
+fi
+rm -f conftest*
+
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_ieee_option" 1>&6
+if test $ac_cv_ieee_option != none; then
+ CFLAGS="${CFLAGS} ${ac_cv_ieee_option}"
+fi
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@CC@%$CC%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@RANLIB@%$RANLIB%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/trio/configure.in b/trio/configure.in
new file mode 100644
index 00000000..6783959b
--- /dev/null
+++ b/trio/configure.in
@@ -0,0 +1,45 @@
+dnl
+dnl Configuration for trio
+dnl
+
+AC_INIT(triodef.h)
+
+AC_PROG_CC
+ifdef([AC_PROG_CC_STDC], [AC_PROG_CC_STDC])
+AC_LANG_C
+
+AC_PROG_INSTALL
+AC_PROG_RANLIB
+
+dnl
+dnl Alpha floating-point compiler option.
+dnl
+
+AC_MSG_CHECKING(for IEEE compilation options)
+AC_CACHE_VAL(ac_cv_ieee_option, [
+AC_TRY_COMPILE(,[
+#if !(defined(__alpha) && (defined(__DECC) || defined(__DECCXX) || (defined(__osf__) && defined(__LANGUAGE_C__))) && (defined(VMS) || defined(__VMS)))
+# error "Option needed"
+#endif
+],ac_cv_ieee_option="/IEEE_MODE=UNDERFLOW_TO_ZERO/FLOAT=IEEE",
+AC_TRY_COMPILE(,[
+#if !(defined(__alpha) && (defined(__DECC) || defined(__DECCXX) || (defined(__osf__) && defined(__LANGUAGE_C__))) && !(defined(VMS) || defined(__VMS)) && !defined(_CFE))
+# error "Option needed"
+#endif
+],ac_cv_ieee_option="-ieee",
+AC_TRY_COMPILE(,[
+#if !(defined(__alpha) && (defined(__GNUC__) && (defined(__osf__) || defined(__linux__))))
+# error "Option needed"
+#endif
+],ac_cv_ieee_option="-mieee",
+ac_cv_ieee_option="none"
+)
+)
+)
+])
+AC_MSG_RESULT($ac_cv_ieee_option)
+if test $ac_cv_ieee_option != none; then
+ CFLAGS="${CFLAGS} ${ac_cv_ieee_option}"
+fi
+
+AC_OUTPUT(Makefile)
diff --git a/trio/doc/doc.h b/trio/doc/doc.h
new file mode 100644
index 00000000..4b368f46
--- /dev/null
+++ b/trio/doc/doc.h
@@ -0,0 +1,161 @@
+/*************************************************************************
+ *
+ * $Id: doc.h,v 1.12 2002/12/08 10:42:49 breese Exp $
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+/**
+@mainpage
+
+@author Bjørn Reese
+@author Daniel Stenberg
+
+@section intro Introduction
+
+Trio is a fully matured and stable set of printf and string functions
+designed be used by applications with focus on portability or with the
+need for additional features that are not supported by standard stdio
+implementation.
+
+There are several cases where you may want to consider using trio:
+
+@li Portability across heterogeneous platforms.
+@li Embedded systems without stdio support.
+@li Extendability of unsupported features.
+@li Your native version does not do everything you need.
+
+When you write applications that must be portable to a wide range of
+platforms you often have to deal with inadequate implementations of the
+stdio library functions. Most notably is the lack of secure formatting
+functions, such as snprintf, or the lack of parameter reordering commonly
+used for the internationalization of applications, such as the <num>$
+modifier. Sometimes the feature you need is simply not present in stdio.
+So you end up spending much effort on determining which platforms supports
+what, and to write your own versions of various features. This is where
+trio can help you. Trio is a platform-independent implementation of the
+stdio printf and scanf functions and the string library functions.
+
+The functionality described in the stdio standards is a compromise, and
+does unfortunately not include a mechanism to extend the functionality for
+an individual application. Oftentimes an application has the need for an
+extra feature, and the application code can become much more clear and
+readable by using an extension mechanism. Trio supports a range of useful
+extensions such as user-defined specifiers, passing of arguments in arrays,
+localized string scanning, thousand-separators, and arbitrary integer bases.
+
+Trio fully implements the C99 (ISO/IEC 9899:1999) and UNIX98 (the Single
+Unix Specification, Version 2) standards, as well as many features from
+other implemenations, e.g. the GNU libc and BSD4.
+
+@section examples Examples
+
+@subsection ex1 Binary Numbers
+Output an integer as a binary number using a trio extension.
+@verbatim
+ trio_printf("%..2i\n", number);
+@endverbatim
+
+@subsection ex2 Thousand-separator
+Output a number with thousand-separator using a trio extension.
+@verbatim
+ trio_printf("%'f\n", 12345.6);
+@endverbatim
+The thousand-separator described by the locale is used.
+
+@subsection ex3 Fixed Length Array and Sticky Modifier
+Output an fixed length array of floating-point numbers.
+@verbatim
+ double array[] = {1.0, 2.0, 3.0};
+ printf("%.2f %.2f %.2f\n", array[0], array[1], array[2]);
+@endverbatim
+The same with two trio extensions (arguments are passed in an array, and
+the first formatting specifier sets the sticky option so we do not have
+to type all the formatting modifiers for the remaining formatting specifiers)
+@verbatim
+ trio_printfv("%!.2f %f %f\n", array);
+@endverbatim
+Another, and more powerful, application of being able to pass arguments in
+an array is the creation of the printf/scanf statement at run-time, where
+the formatting string, and thus the argument list, is based on an external
+configuration file.
+
+@subsection ex4 Localized scanning
+Parse a string consisting of one or more upper-case alphabetic characters
+followed by one or more numeric characters.
+@verbatim
+ sscanf(buffer, "%[A-Z]%[0-9]", alphabetic, numeric);
+@endverbatim
+The same but with locale using a trio extension.
+@verbatim
+ trio_sscanf(buffer, "%[[:upper:]]%[[:digit:]]", alphabetic, numeric);
+@endverbatim
+
+@section legal Legal Issues
+Trio is distributed under the following license, which allows practically
+anybody to use it in almost any kind of software, including proprietary
+software, without difficulty.
+
+"Copyright (C) 1998-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."
+
+@section contribution Contribution
+
+@subsection contribute Contribute
+We appreciate any type of contribution, from ideas over improvements to
+error corrections.
+
+The project space contains references to bug and feature tracking,
+mailing-list, and the CVS repository. We prefer communication via the
+mailing-list, but do not require you to be subscribed, because trio is a
+small project.
+
+The project space is located at http://sourceforge.net/projects/ctrio/
+
+@subsection contributors Contributors
+We have received contributions from the following persons (in alphabetic
+order sorted by surname)
+
+@li Craig Berry
+@li Stan Boehm
+@li Robert Collins
+@li Danny Dulai
+@li John Fotheringham
+@li Markus Henke
+@li Ken Gibson
+@li Paul Janzen
+@li Richard Jinks
+@li Tero Jänkä
+@li Howard Kapustein
+@li Rune Enggaard Lausen
+@li Mehdi Lavasani
+@li Alexander Lukyanov
+@li Emmanuel Mogenet
+@li Jacob Navia
+@li Jose Ortiz
+@li Joe Orton
+@li Gisli Ottarsson
+@li Marc Werwerft
+@li Igor Zlatkovic
+
+Please let us know, and accept our apology, if we have omitted anybody.
+
+*/
diff --git a/trio/doc/doc_dynamic.h b/trio/doc/doc_dynamic.h
new file mode 100644
index 00000000..92482676
--- /dev/null
+++ b/trio/doc/doc_dynamic.h
@@ -0,0 +1,31 @@
+/*************************************************************************
+ *
+ * $Id: doc_dynamic.h,v 1.1 2001/12/27 17:29:20 breese Exp $
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+/** @addtogroup DynamicStrings Dynamic String Functions.
+Dynamic string functions.
+
+@b SYNOPSIS
+
+@verbatim
+cc ... -ltrio -lm
+
+#include <triostr.h>
+@endverbatim
+
+@b DESCRIPTION
+
+*/
diff --git a/trio/doc/doc_printf.h b/trio/doc/doc_printf.h
new file mode 100644
index 00000000..4321cd5c
--- /dev/null
+++ b/trio/doc/doc_printf.h
@@ -0,0 +1,532 @@
+/*************************************************************************
+ *
+ * $Id: doc_printf.h,v 1.3 2002/05/07 16:26:00 breese Exp $
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+/** @addtogroup Printf Formatted Printing Functions.
+Variations of formatted printing functions.
+
+@b SYNOPSIS
+
+@verbatim
+cc ... -ltrio -lm
+
+#include <trio.h>
+@endverbatim
+
+@b DESCRIPTION
+
+This documentation is incomplete.
+The documentation of the printf family in [C99] and [UNIX98] also applies
+to the trio counterparts.
+
+All these functions outputs a string which is formatted according to the
+@p format string and the consecutive arguments. The @p format string is
+described in the Formatting section below.
+
+@ref trio_printf, @ref trio_vprintf, and @ref trio_printfv writes the
+output to the standard output stream (stdout).
+
+@ref trio_fprintf, @ref trio_vfprintf, and @ref trio_fprintfv writes the
+output to a given output stream.
+
+@ref trio_dprintf, @ref trio_vdprintf, and @ref trio_dprintfv writes the
+output to a file descriptor (this includes, for example, sockets).
+
+@ref trio_sprintf, @ref trio_vsprintf, and @ref trio_sprintfv writes the
+output into @p buffer.
+
+@ref trio_snprintf, @ref trio_vsnprintf, and @ref trio_snprintfv writes @p
+max - 1 characters into @p buffer followed by a terminating zero character.
+If @p max is 1, then @p buffer will be an empty string. If @p max is 0,
+then @p buffer is left untouched, and can consequently be NULL. The number
+of characters that would have been written to @p buffer, had there been
+sufficient space, is returned.
+
+@ref trio_snprintfcat appends the formatted text at the end of @p buffer.
+
+@ref trio_asprintf and @ref trio_vasprintf allocates and returns an
+allocated string in @p buffer containing the formatted text.
+
+@b FORMATTING
+
+The @p format string can contain normal text and conversion indicators.
+The normal text can be any character except the nil character (\000 =
+'\0') and the percent character (\045 = '%'). Conversion indicators
+consists of an indication character (%), followed by zero or more conversion
+modifiers, and exactly one conversion specifier.
+
+@b Modifiers
+
+Some modifiers exhibit the same behaviour for all specifiers, other modifiers
+indicate different behaviours for different specifiers, and other modifiers
+are only applicable to certain specifiers. The relationship is described for
+each modifier. The number 9 is used to denotes an arbitrary integer.
+
+@em Positional ( @c 9$ ) [UNIX98]
+
+Normally the arguments supplied to these functions are interpreted
+incrementially from left to right. Arguments can be referenced specifically in
+the format string. The modifier n$ selects the nth argument. The first
+argument is referred as 1$. If this modifier is used, it must be the first
+modifier after the indication character. n$ can also be used for argument
+width, precision, and base.
+
+The performance penalty of using positionals is almost neglible (contrary to
+most other printf implementations).
+
+@li @em Reference @em Mix.
+Mixing normal and positional specifiers is allowed [TRIO]. For example,
+@verbatim
+ trio_printf("%d %3$d %2$d\n", 1, 2, 3);
+@endverbatim
+results in
+@verbatim
+ 1 3 2
+@endverbatim
+Arguments for the printf family are passed on the stack. On most platforms it
+is not possible to determine the size of individual stack elements, so it is
+essential that the format string corresponds exactly to the passed arguments.
+If this is not the case, incorrect values may be put into the result.
+
+@li @em Reference @em Gap.
+For the same reason it is also essential that the format string does not
+contain any &quot;gaps&quot; in the positional arguments. For example,
+@verbatim
+ trio_printf("%1$d %3$d\n", 1, 2, 3);
+@endverbatim
+is NOT allowed. The format string parser has no knowledge about whether the
+second argument is, say, an integer or a long double (which have different
+sizes).
+@verbatim
+@endverbatim
+[UNIX98] describes this as unspecified behaviour. [TRIO] will detect reference
+gaps and return an error.
+
+@li @em Double @em Reference.
+It is also not allowed to reference an argument twice or more. For example,
+@verbatim
+ trio_printf("%1$d %1$lf\n", 1);
+@endverbatim
+is NOT allowed, because it references the first argument as two differently
+sized objects.
+@verbatim
+@endverbatim
+[UNIX98] describes this as unspecified behaviour. [TRIO] will detect double
+references and return an error.
+
+The following two statements are equivalent
+@verbatim
+ trio_printf("|%d %s\n|", 42, "meanings");
+ |42 meanings|
+
+ trio_printf("|%1$d %2$s|\n", 42, "meanings");
+ |42 meanings|
+@endverbatim
+
+@em Width ( @c 9 )
+
+Specifies the minimum width of a field. If the fields has less characters than
+specified by the width, the field will be left adjusted and padded by spaces.
+The adjustment and padding can be changed by the Alignment ( @c - ) and
+Padding ( @c 0 ) modifiers.
+
+The width is specified as a number. If an asterix ( @c * ) is used instead, the
+width will be read from the argument list.
+
+Prefixes, such as 0x for hexadecimal integers, are part of width.
+@verbatim
+ trio_printf("|%10i|\n", 42);
+ | 42|
+@endverbatim
+
+@em Precision ( @c .9 )
+
+The precision has different semantics for the various data types.
+The precision specifies the maximum number of printed characters for strings,
+the number of digits after the decimal-point for floating-point numbers,
+the number of significant digits for the @c g (and @c G) representation of
+floating-point numbers, the minimum number of printed digits for integers.
+@verbatim
+ trio_printf("|%10.8i|%.8i|\n", 42, 42);
+ | 00000042|00000042|
+@endverbatim
+
+@em Base ( @c ..9 ) [TRIO]
+
+Sets the base that the associated integer must be converted to. The base can
+be between 2 and 36 (both included).
+@verbatim
+ trio_printf("|%10.8.2i|%10..2i|%..2i|\n", 42, 42, 42);
+ | 00101010| 101010|101010|
+
+ trio_printf("|%*.8.*i|\n", 10, 2, 42);
+ | 00101010|
+@endverbatim
+
+@em Padding ( @c 0 )
+
+Integer and floating point numbers are prepended by zeros. The number of
+leading zeros are determined by the precision. If precision is not present,
+width is used instead.
+
+@em Short ( @c h )
+
+Integer arguments are read as an ( @c unsigned ) @c short @c int. String
+and character arguments are read as @c char @c * and @c char respectively.
+
+@em Short @em short ( @c hh ) [C99, GNU]
+
+The argument is read as an ( @c unsigned ) @c char.
+
+@em Fixed @em Size ( @c I ) [MSVC]
+
+The argument is read as a fixed sized integer. The modifier is followed by
+a number, which specifies the number of bits in the integer, and can be one
+of the following
+
+@li @c I8
+@li @c I16
+@li @c I32
+@li @c I64 (if 64-bits integers are supported)
+
+Works only for integers (i, u, d, o, x, X)
+
+@em Largest ( @c j ) [C99]
+
+The argument is read as an @c intmax_t / @c uintmax_t, which is defined to
+be the largest signed/unsigned integer.
+
+@em Long ( @c l )
+
+An integral argument is read as an ( @c unsigned ) @c long @c int. A string
+argument is read as a @c wchar_t @c *, and output as a multi-byte character
+sequence.
+
+@em Long @em long ( @c ll ) [C99, UNIX98, GNU]
+
+The argument is read as an ( @c unsigned ) @c long @c long @c int.
+
+@em Long @em double ( @c L ) [C99, UNIX98, GNU]
+
+The argument is read as a @c long @c double.
+
+@em ptrdiff_t ( @c t ) [C99]
+
+The argument is read as a @c ptrdiff_t, which is defined to be the signed
+integer type of the result of subtracting two pointers.
+
+@em Quad ( @c q ) [BSD, GNU]
+
+Corresponds to the long long modifier ( @c ll ).
+
+@em Wide ( @c w ) [MISC]
+
+For a string argument this is equivalent to using the long modifier ( @c l ).
+
+@em size_t ( @c z ) [C99]
+
+The argument is read as a @c size_t, which is defined to be the type
+returned by the @c sizeof operator.
+
+@em size_t ( @c Z ) [GNU]
+
+Corresponds to the size_t modifier ( @c z ).
+
+@em Alternative ( @c # )
+
+Prepend radix indicator for hexadecimal, octal, and binary integer numbers
+and for pointers.
+Always add a decimal-pointer for floating-point numbers.
+Escape non-printable characters for strings.
+
+@em Spacing ( )
+
+Prepend leading spaces when necessary.
+
+@em Sign ( @c + )
+
+Always prepend a sign to numbers. Normally only the negative sign is prepended
+to a number. With this modifier the positive sign may also be prepended.
+
+@em Alignment ( @c - )
+
+The output will be left-justified in the field specified by the width.
+
+@em Argument ( @c * )
+
+Width, precision, or base is read from the argument list, rather than from
+the formatting string.
+
+@em Quote / @em Grouping ( @c ' ) [MISC]
+
+Groups integers and the integer-part of floating-point numbers according to
+the locale. Quote strings and characters.
+
+@em Sticky ( @c ! ) [TRIO]
+
+The modifiers listed for the current specifier will be reused by subsequent
+specifiers of the same group.
+The following specifier groups exists
+@li Integer ( @c i, @c u, @c d, @c o, @c x, @c X )
+@li Floating-point ( @c f, @c F, @c e, @c E, @c g, @c G, @c a, @c A )
+@li Character ( @c c )
+@li String ( @c s )
+@li Pointer ( @c p )
+@li Count ( @c n )
+@li Errno ( @c m )
+@li Group ( @c [] )
+
+The sticky modifiers are active until superseeded by other sticky modifiers,
+or the end of the format string is reached.
+Local modifiers overrides sticky modifiers for the given specifier only.
+@verbatim
+ trio_printf("|%!08#x|%04x|%x|\n", 42, 42, 42);
+ |0x00002a|0x2a|0x00002a|
+@endverbatim
+
+@b Specifiers
+
+@em Percent ( @c % )
+
+Produce a percent ( @c % ) character. This is used to quote the indication
+character. No modifiers are allowed.
+The full syntax is @c %%.
+@verbatim
+ trio_printf("Percent is %%\n");
+ Percent is %
+@endverbatim
+
+@em Hex @em floats ( @c a, @c A ) [C99]
+
+Output a hexadecimal (base 16) representation of a floating point number. The
+number is automatically preceeded by @c 0x ( or @c 0X ). The exponent is
+@c p ( or @c P ).
+@verbatim
+ trio_printf("|%a|%A|\n", 3.1415, 3.1415e20);
+ |0x3.228bc|0X3.228BCP+14|
+@endverbatim
+
+@em Binary @em numbers ( @c b, @c B ) [MISC - SCO UnixWare 7]
+
+DEPRECATED: Use Base modifier @c %..2i instead.
+
+@em Character ( @c c )
+
+Output a single character.
+
+@li Quote ( @c ' ) [TRIO].
+Quote the character.
+
+@em Decimal ( @c d )
+
+Output a decimal (base 10) representation of a number.
+
+@li Grouping ( @c ' ) [TRIO].
+The number is separated by the locale thousand separator.
+@verbatim
+ trio_printf("|%'ld|\n", 1234567);
+ |1,234,567|
+@endverbatim
+
+@em Floating-point ( @c e, @c E)
+
+Output a decimal floating-point number.
+The style is @c [-]9.99e[-]9, where
+@li @c [-]9.99 is the mantissa (as described for the @c f, @c F specifier), and
+@li @c e[-]9 is the exponent indicator (either @c e or @c E, depending on the
+floating-point specifier), followed by an optional sign and the exponent
+
+If the precision is wider than the maximum number of digits that can be
+represented by the floating-point unit, then the number will be adequately
+rounded. For example, assuming DBL_DIG is 15
+@verbatim
+ trio_printf("|%.18e|\n", (1.0 / 3.0));
+ |3.333333333333333000e-01|
+@endverbatim
+
+@em Floating-point ( @c f, @c F )
+
+Output a decimal floating-point number.
+The style is @c [-]9.99, where
+@li @c [-] is an optional sign (either @c + or @c -),
+@li @c 9 is the integer-part (possibly interspersed with thousand-separators),
+@li @c . is the decimal-point (depending on the locale), and
+@li @c 99 is the fractional-part.
+
+If more digits are needed to output the number, than can be represented with
+the accuracy of the floating-point unit, then the number will be adequately
+rounded. For example, assuming that DBL_DIG is 15
+@verbatim
+ trio_printf("|%f|\n", (2.0 / 3.0) * 1E18);
+ |666666666666666700.000000|
+@endverbatim
+
+The following modifiers holds a special meaning for this specifier
+@li Alternative ( @c # ) [C99].
+Add decimal point.
+@li Grouping ( @c ' ) [TRIO].
+Group integer part of number into thousands (according to locale).
+
+@em Floating-point ( @c g, @c G)
+
+Output a decimal floating-point representation of a number. The format of
+either the @c f, @c F specifier or the @c e, @c E specifier is used, whatever
+produces the shortest result.
+
+@em Integer ( @c i )
+
+Output a signed integer. Default base is 10.
+
+@em Errno ( @c m ) [GNU]
+
+@em Count ( @c n )
+
+Insert into the location pointed to by the argument, the number of octets
+written to the output so far.
+
+@em Octal ( @c o )
+
+Output an octal (base 8) representation of a number.
+
+@em Pointer ( @c p )
+
+Ouput the address of the argument. The address is printed as a hexadecimal
+number. If the argument is the NULL pointer the text @c (nil) will be used
+instead.
+@li Alternative ( @c # ) [TRIO].
+Prepend 0x
+
+@em String ( @c s, @c S )
+
+Output a string. The argument must point to a zero terminated string. If the
+argument is the NULL pointer the text @c (nil) will be used instead.
+@c S is equivalent to @c ls.
+@li Alternative ( @c # ) [TRIO].
+Escape non-printable characters.
+
+Non-printable characters are converted into C escapes, or hexadecimal numbers
+where no C escapes exists for the character. The C escapes, the hexadecimal
+number, and all backslashes are prepended by a backslash ( @c \ ).
+The supported C escapes are
+@li @c \a (\007) = alert
+@li @c \b (\010) = backspace
+@li @c \f (\014) = formfeed
+@li @c \n (\012) = newline
+@li @c \r (\015) = carriage return
+@li @c \t (\011) = horizontal tab
+@li @c \v (\013) = vertical tab
+
+@verbatim
+ trio_printf("|One %s Three|One %'s Three|\n", "Two", "Two");
+ |One Two Three|One "Two" Three|
+
+ trio_printf("|Argument missing %s|\n", NULL);
+ |Argument missing (nil)|
+
+ trio_printf("|%#s|\n", "\007 \a.");
+ |\a \a.|
+@endverbatim
+
+@em Unsigned ( @c u )
+
+Output an unsigned integer. Default base is 10.
+
+@em Hex ( @c x, @c X )
+
+Output a hexadecimal (base 16) representation of a number.
+
+@li Alternative ( @c # ).
+Preceed the number by @c 0x ( or @c 0X ). The two characters are counted
+as part of the width.
+
+@em User-defined ( @c <> )
+
+Invoke user-defined formatting.
+See @ref trio_register for further information.
+
+@b RETURN @b VALUES
+
+All functions returns the number of outputted characters. If an error occured
+then a negative error code is returned [TRIO]. Note that this is a deviation
+from the standard, which simply returns -1 (or EOF) and errno set
+appropriately.
+The error condition can be detected by checking whether the function returns
+a negative number or not, and the number can be parsed with the following
+macros. The error codes are primarily intended as debugging aide for the
+developer.
+
+@li TRIO_EINVAL: Invalid argument.
+@li TRIO_ETOOMANY: Too many arguments.
+@li TRIO_EDBLREF: Double argument reference.
+@li TRIO_EGAP: Argument reference gap.
+@li TRIO_ENOMEM: Out of memory.
+@li TRIO_ERANGE: Invalid range.
+@li TRIO_ERRNO: The error is specified by the errno variable.
+
+Example:
+@verbatim
+ int rc;
+
+ rc = trio_printf("%r\n", 42);
+ if (rc < 0) {
+ if (TRIO_ERROR_CODE(rc) != TRIO_EOF) {
+ trio_printf("Error: %s at position %d\n",
+ TRIO_ERROR_NAME(rc),
+ TRIO_ERROR_POSITION(rc));
+ }
+ }
+@endverbatim
+
+@b SEE @b ALSO
+
+@e trio_scanf, @e trio_register.
+
+@b NOTES
+
+The printfv family uses an array rather than the stack to pass arguments.
+This means that @c short @c int and @c float values will not be handled by
+the default argument promotion in C. Instead, these values must be explicitly
+converted with the Short (h) modifier in both cases.
+
+Example:
+@verbatim
+ void *array[2];
+ float float_number = 42.0;
+ short short_number = 42;
+
+ array[0] = &float_number;
+ array[1] = &short_number;
+
+ trio_printfv("%hf %hd\n", array); /* CORRECT */
+ trio_printfv("%f %d\n", array); /* WRONG */
+@endverbatim
+
+@b CONFORMING @b TO
+
+Throughout this document the following abbreviations have been used to
+indicate what standard a feature conforms to. If nothing else is indicated
+ANSI C (C89) is assumed.
+
+@li [C89] ANSI X3.159-1989
+@li [C99] ISO/IEC 9899:1999
+@li [UNIX98] The Single UNIX Specification, Version 2
+@li [BSD] 4.4BSD
+@li [GNU] GNU libc
+@li [MSVC] Microsoft Visual C
+@li [MISC] Other non-standard sources
+@li [TRIO] Extensions specific for this package
+
+*/
diff --git a/trio/doc/doc_register.h b/trio/doc/doc_register.h
new file mode 100644
index 00000000..03610bfa
--- /dev/null
+++ b/trio/doc/doc_register.h
@@ -0,0 +1,357 @@
+/*************************************************************************
+ *
+ * $Id: doc_register.h,v 1.2 2002/04/20 13:28:09 breese Exp $
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+/** @addtogroup UserDefined User-defined Formatted Printing Functions.
+Functions for using customized formatting specifiers.
+
+@b SYNOPSIS
+
+@verbatim
+cc ... -ltrio -lm
+
+#include <trio.h>
+#include <triop.h>
+@endverbatim
+
+@b DESCRIPTION
+
+This documentation is incomplete.
+
+@b User-defined @b Specifier
+
+The user-defined specifier consists of a start character (\074 = '<'), an
+optional namespace string followed by a namespace separator (\072 = ':'),
+a format string, and an end character (\076 = '>').
+
+The namespace string can consist of alphanumeric characters, and is used to
+define a named reference (see below). The namespace is case-sensitive. If no
+namespace is specified, then we use an unnamed reference (see below).
+
+The format can consist of any character except the end character ('>'), the
+namespace separator (':'), and the nil character (\000).
+
+Any modifier can be used together with the user-defined specifier.
+
+@b Registering
+
+A user-defined specifier must be registered before it can be used.
+Unregistered user-defined specifiers are ignored. The @ref trio_register
+function is used to register a user-defined specifier. It takes two argument,
+a callback function and a namespace, and it returns a handle. The handle must
+be used to unregister the specifier later.
+
+The following example registers a user-define specifier with the "my_namespace"
+namespace:
+
+@verbatim
+ my_handle = trio_register(my_callback, "my_namespace");
+@endverbatim
+
+There can only be one user-defined specifier with a given namespace. There
+can be an unlimited number (subject to maximum length of the namespace) of
+different user-defined specifiers.
+
+Passing NULL as the namespace argument results in an anonymous reference.
+There can be an unlimited number of anonymous references.
+
+@b REFERENCES
+
+There are two ways that a registered callback can be called. Either the
+user-defined specifier must contain the registered namespace in the format
+string, or the handle is passed as an argument to the formatted printing
+function.
+
+If the namespace is used, then a user-defined pointer must be passed as an
+argument:
+
+@verbatim
+ trio_printf("<my_namespace:format>\n", my_data);
+@endverbatim
+
+If the handle is used, then the user-defined specifier must not contain a
+namespace. Instead the handle must be passed as an argument, followed by a
+user-defined pointer:
+
+@verbatim
+ trio_printf("<format>\n", my_handle, my_data);
+@endverbatim
+
+The two examples above are equivalent.
+
+There must be exactly one user-defined pointer per user-defined specifier.
+This pointer can be used within the callback function with the
+@ref trio_get_argument getter function (see below).
+
+The format string is optional. It can be used within the callback function
+with the @ref trio_get_format getter function.
+
+@b Anonymous @b References
+Anonymous references are specified by passing NULL as the namespace.
+
+The handle must be passed as an argument followed by a user-defined pointer.
+No namespace can be specified.
+
+@verbatim
+ anon_handle = trio_register(callback, NULL);
+ trio_printf("<format>\n", anon_handle, my_data);
+@endverbatim
+
+@b Restrictions
+
+@li The length of the namespace string cannot exceed 63 characters.
+@li The length of the user-defined format string cannot exceed 255 characters.
+@li User-defined formatting cannot re-define existing specifiers.
+This restriction was imposed because the existing formatting specifiers have
+a well-defined behaviour, and any re-definition would apply globally to an
+application (imagine a third-party library changing the behaviour of a
+specifier that is crusial to your application).
+
+@b CALLBACK @b FUNCTION
+
+The callback function will be called if a matching user-defined specifier
+is found within the formatting string. The callback function takes one input
+parameter, an opaque reference which is needed by the private functions. It
+returns an @c int, which is currently ignored. The prototype is
+
+@verbatim
+ int (*trio_callback_t)(void *ref);
+@endverbatim
+
+See the Example section for full examples.
+
+@b PRINTING @b FUNCTIONS
+
+The following printing functions must only be used inside a callback function.
+These functions will print to the same output medium as the printf function
+which invoked the callback function. For example, if the user-defined
+specifier is used in an sprintf function, then these print functions will
+output their result to the same string.
+
+@b Elementary @b Printing
+
+There are a number of function to print elementary data types.
+
+@li @ref trio_print_int Print a signed integer. For example:
+@verbatim
+ trio_print_int(42);
+@endverbatim
+@li @ref trio_print_uint Print an unsigned integer.
+@li @ref trio_print_double Print a floating-point number.
+@li @ref trio_print_string Print a string. For example:
+@verbatim
+ trio_print_string("Hello World");
+ trio_print_string(trio_get_format());
+@endverbatim
+@li @ref trio_print_pointer Print a pointer.
+
+@b Formatted @b Printing
+
+The functions @ref trio_print_ref, @ref trio_vprint_ref, and
+@ref trio_printv_ref outputs a formatted string just like its printf
+equivalents.
+
+@verbatim
+ trio_print_ref(ref, "There are %d towels\n", 42);
+ trio_print_ref(ref, "%<recursive>\n", recursive_writer, trio_get_argument());
+@endverbatim
+
+@b GETTER @b AND @b SETTER @b FUNCTIONS
+
+The following getter and setter functions must only be used inside a callback
+function. They can either operate on the modifiers or on special data.
+
+@b Modifiers
+
+The value of a modifier, or a boolean indication of its presence or absence,
+can be found or set with the getter and setter functions.
+The generic prototypes of the these getter and setter functions are
+
+@verbatim
+ int trio_get_???(void *ref);
+ void trio_set_???(void *ref, int);
+@endverbatim
+
+where @c ??? refers to a modifier. For example, to get the width of the
+user-defined specifier use
+
+@verbatim
+ int width = trio_get_width(ref);
+@endverbatim
+
+@b Special @b Data
+
+Consider the following user-defined specifier, in its two possible referencing
+presentations.
+
+@verbatim
+ trio_printf("%<format>\n", namespace_writer, argument);
+ trio_printf("%<namespace:format>\n", argument);
+@endverbatim
+
+@ref trio_get_format will get the @p format string, and
+@ref trio_get_argument} will get the @p argument parameter.
+There are no associated setter functions.
+
+@b EXAMPLES
+
+The following examples show various types of user-defined specifiers. Although
+each specifier is demonstrated in isolation, they can all co-exist within the
+same application.
+
+@b Time @b Example
+
+Print the time in the format "HOUR:MINUTE:SECOND" if "time" is specified inside
+the user-defined specifier.
+
+@verbatim
+ static int time_writer(void *ref)
+ {
+ const char *format;
+ time_t *data;
+ char buffer[256];
+
+ format = trio_get_format(ref);
+ if ((format) && (strcmp(format, "time") == 0)) {
+ data = trio_get_argument(ref);
+ if (data == NULL)
+ return -1;
+ strftime(buffer, sizeof(buffer), "%H:%M:%S", localtime(data));
+ trio_print_string(ref, buffer);
+ }
+ return 0;
+ }
+@endverbatim
+
+@verbatim
+ int main(void)
+ {
+ void *handle;
+ time_t now = time(NULL);
+
+ handle = trio_register(time_print, "my_time");
+
+ trio_printf("%<time>\n", handle, &now);
+ trio_printf("%<my_time:time>\n", &now);
+
+ trio_unregister(handle);
+ return 0;
+ }
+@endverbatim
+
+@b Complex @b Numbers @b Example
+
+Consider a complex number consisting of a real part, re, and an imaginary part,
+im.
+
+@verbatim
+ struct Complex {
+ double re;
+ double im;
+ };
+@endverbatim
+
+This example can print such a complex number in one of two formats.
+The default format is "re + i im". If the alternative modifier is used, then
+the format is "r exp(i theta)", where r is the length of the complex vector
+(re, im) and theta is its angle.
+
+@verbatim
+ static int complex_print(void *ref)
+ {
+ struct Complex *data;
+ const char *format;
+
+ data = (struct Complex *)trio_get_argument(ref);
+ if (data) {
+ format = trio_get_format(ref);
+
+ if (trio_get_alternative(ref)) {
+ double r, theta;
+
+ r = sqrt(pow(data->re, 2) + pow(data->im, 2));
+ theta = acos(data->re / r);
+ trio_print_ref(ref, "%#f exp(i %#f)", r, theta);
+
+ } else {
+ trio_print_ref(ref, "%#f + i %#f", data->re, data->im);
+ }
+ }
+ return 0;
+ }
+@endverbatim
+
+@verbatim
+ int main(void)
+ {
+ void *handle;
+
+ handle = trio_register(complex_print, "complex");
+
+ /* Normal format. With handle and the with namespace */
+ trio_printf("%<>\n", handle, &complex);
+ trio_printf("%<complex:>\n", &complex);
+ /* In exponential notation */
+ trio_printf("%#<>\n", handle, &complex);
+ trio_printf("%#<complex:unused data>\n", &complex);
+
+ trio_unregister(handle);
+ return 0;
+ }
+@endverbatim
+
+@b RETURN @b VALUES
+
+@ref trio_register returns a handle, or NULL if an error occured.
+
+@b SEE @b ALSO
+
+@ref trio_printf
+
+@b NOTES
+
+User-defined specifiers, @ref trio_register, and @ref trio_unregister are
+not thread-safe. In multi-threaded applications they must be guarded by
+mutexes. Trio provides two special callback functions, called ":enter" and
+":leave", which are invoked every time a thread-unsafe operation is attempted.
+As the thread model is determined by the application, these callback functions
+must be implemented by the application.
+
+The following callback functions are for demonstration-purposes only.
+Replace their bodies with locking and unlocking of a mutex to achieve
+thread-safety.
+@verbatim
+ static int enter_region(void *ref)
+ {
+ fprintf(stderr, "Enter Region\n");
+ return 1;
+ }
+
+ static int leave_region(void *ref)
+ {
+ fprintf(stderr, "Leave Region\n");
+ return 1;
+ }
+@endverbatim
+These two callbacks must be registered before other callbacks are registered.
+@verbatim
+ trio_register(enter_region, ":enter");
+ trio_register(leave_region, ":leave");
+
+ another_handle = trio_register(another_callback, NULL);
+@endverbatim
+
+*/
diff --git a/trio/doc/doc_scanf.h b/trio/doc/doc_scanf.h
new file mode 100644
index 00000000..4d997d40
--- /dev/null
+++ b/trio/doc/doc_scanf.h
@@ -0,0 +1,120 @@
+/*************************************************************************
+ *
+ * $Id: doc_scanf.h,v 1.1 2001/12/27 17:29:20 breese Exp $
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+/** @addtogroup Scanf Formatted Scanning Functions.
+Variations of formatted scanning functions.
+
+@b SYNOPSIS
+
+@verbatim
+cc ... -ltrio -lm
+
+#include <trio.h>
+@endverbatim
+
+@b DESCRIPTION
+
+This documentation is incomplete.
+The documentation of the scanf family in [C99] and [UNIX98] also applies
+to the trio counterparts.
+
+@b SCANNING
+
+The scanning is controlled by the format string.
+The format string can contain normal text and conversion indicators.
+The normal text can be any character except the nil character
+(\000) and the percent character (\045 = '\%').
+Conversion indicators consists of an indication character (%), followed by
+zero or more conversion modifiers, and exactly one conversion specifier.
+
+@b Modifiers
+
+@em Positional ( @c 9$ ) [UNIX98]
+
+See @ref trio_printf.
+
+@b Specifiers
+
+@em Percent ( @c % )
+
+@em Character ( @c c )
+
+@em Decimal ( @c d )
+
+@em Floating-point ( @c a, @c A, @c e, @c E, @c f, @c F, @c g, @c G )
+
+@em Integer ( @c i )
+
+@em Count ( @c n )
+
+@em Octal ( @c o )
+
+@em Pointer ( @c p )
+
+@em String ( @c s )
+
+@em Unsigned ( @c u )
+
+@em Hex ( @c x, @c X )
+
+@em Scanlist ( @c [] )
+
+Scanlist Exclusion (@c ^ )
+
+Scanlist Range ( @c - ) [TRIO]
+
+@li Only increasing ranges, i.e. @c [a-b], but not @c [b-a].
+@li Transitive ranges, ie. @c [a-b-c] equals @c [a-c].
+@li Trailing minus, ie. @c [a-] is interpreted as an @c a and a @c -.
+@li Duplicates are ignored.
+
+Scanlist Equivalence Class Expression ( @c [= @c =] ) [TRIO]
+
+Locale dependent (LC_COLLATE).
+Only one expression can appear inside the delimiters.
+@li @c [=a=] All letters in the same equivalence class as the letter @c a.
+@verbatim
+ trio_scanf("%[[=a=]b]\n", buffer);
+ trio_scanf("%[[=a=][=b=]]\n", buffer);
+@endverbatim
+
+Scanlist Character Class Expression ( @c [: @c :]) [TRIO]
+Locale dependent (LC_CTYPE).
+Only one expression can appear inside the delimiters.
+@li @c [:alnum:] Same as @c [:alpha:] and @c [:digit:]
+@li @c [:alpha:] Same as @c [:lower:] and @c [:upper:]
+@li @c [:cntrl:] Control characters
+@li @c [:digit:] Decimal digits
+@li @c [:graph:] Printable characters except space
+@li @c [:lower:] Lower case alphabetic letters
+@li @c [:print:] Printable characters
+@li @c [:punct:] Punctuation
+@li @c [:space:] Whitespace characters
+@li @c [:upper:] Upper case alphabetic letters
+@li @c [:xdigit:] Hexadecimal digits
+@verbatim
+ trio_scanf("%[[:alnum:]]\n", buffer);
+ trio_scanf("%[[:alpha:][:digit:]]\n", buffer);
+@endverbatim
+
+@b RETURN @b VALUES
+
+@b SEE @b ALSO
+
+@ref trio_printf
+
+*/
diff --git a/trio/doc/doc_static.h b/trio/doc/doc_static.h
new file mode 100644
index 00000000..6816196d
--- /dev/null
+++ b/trio/doc/doc_static.h
@@ -0,0 +1,61 @@
+/*************************************************************************
+ *
+ * $Id: doc_static.h,v 1.1 2001/12/27 17:29:20 breese Exp $
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+/** @addtogroup StaticStrings Static String Functions.
+Replacements for the standard C string functions.
+
+@b SYNOPSIS
+
+@verbatim
+cc ... -ltrio -lm
+
+#include <triostr.h>
+@endverbatim
+
+@b DESCRIPTION
+
+This package renames, fixes, and extends the standard C string handling
+functions.
+
+@b Naming
+
+Renaming is done to provide more clear names, to provide a consistant naming
+and argument policy, and to hide portability issues.
+
+@li All functions starts with "trio_".
+@li Target is always the first argument, if present, except where the target
+is optional, such as @ref trio_to_double.
+@li Functions requiring a size for target includes "_max" in its name, and
+the size is always the second argument.
+@li Functions performing case-sensitive operations includes "_case" in its
+name.
+
+@b Fixing
+
+Fixing is done to avoid subtle error conditions.
+For example, @c strncpy does not terminate the result with a zero if the
+source string is bigger than the maximal length, so technically the result
+is not a C string anymore. @ref trio_copy_max makes sure that the result
+is zero terminated.
+
+@b Extending
+
+Extending is done to provide a richer set of fundamental functions.
+This includes functionality such as wildcard matching ( @c trio_match )
+and calculation of hash values ( @c trio_hash ).
+
+*/
diff --git a/trio/doc/footer.html b/trio/doc/footer.html
new file mode 100644
index 00000000..0e97ca00
--- /dev/null
+++ b/trio/doc/footer.html
@@ -0,0 +1,4 @@
+<HR>
+<center class="copyright">Copyright (C) 2001 Bj&oslash;rn Reese and Daniel Stenberg.</center>
+</body>
+</html>
diff --git a/trio/doc/header.html b/trio/doc/header.html
new file mode 100644
index 00000000..fd2edd1b
--- /dev/null
+++ b/trio/doc/header.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+ <title>TRIO</title>
+ <link href="trio.css" rel="stylesheet" type="text/css">
+</head>
+<body>
diff --git a/trio/doc/trio.cfg b/trio/doc/trio.cfg
new file mode 100644
index 00000000..4bc1ee67
--- /dev/null
+++ b/trio/doc/trio.cfg
@@ -0,0 +1,873 @@
+# Doxyfile 1.2.12
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = TRIO
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY =
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Chinese, Croatian, Czech, Danish, Dutch, Finnish, French,
+# German, Hungarian, Italian, Japanese, Korean, Norwegian, Polish,
+# Portuguese, Romanian, Russian, Slovak, Slovene, Spanish and Swedish.
+
+OUTPUT_LANGUAGE = English
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = YES
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these class will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = YES
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. It is allowed to use relative paths in the argument list.
+
+STRIP_FROM_PATH =
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower case letters. If set to YES upper case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# users are adviced to set this option to NO.
+
+CASE_SENSE_NAMES = NO
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explict @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# reimplements.
+
+INHERIT_DOCS = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consist of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C.
+# For instance some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text.
+
+WARN_FORMAT =
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = . doc
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank file matching one of the following patterns are included:
+# *.c *.cc *.cxx *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp
+# *.h++ *.idl
+
+FILE_PATTERNS = *.h *.c
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+
+EXCLUDE_PATTERNS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH = doc
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+
+INPUT_FILTER =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse.
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT =
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER = doc/header.html
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER = doc/footer.html
+
+# The HTML_STYLESHEET tag can be used to specify a user defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet
+
+HTML_STYLESHEET = doc/trio.css
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the Html help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript and frames is required (for instance Mozilla, Netscape 4.0+,
+# or Internet explorer 4.0+). Note that for large projects the tree generation
+# can take a very long time. In such cases it is better to disable this feature.
+# Windows users are probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT =
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimised for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT =
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assigments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT =
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION =
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_XML = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF = YES
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed.
+
+PREDEFINED = __STDC__=1 TRIO_DOCUMENTATION= TRIO_PUBLIC= TRIO_PRIVATE=static TRIO_CONST=const TRIO_VOLATILE=volatile TRIO_SIGNED=signed TRIO_INLINE=inline TRIO_NOARGS=void TRIO_ARGS1(z,a)=(a) TRIO_ARGS2(z,a,b)=(a,b) TRIO_ARGS3(z,a,b,c)=(a,b,c) TRIO_ARGS4(z,a,b,c,d)=(a,b,c,d) TRIO_ARGS5(z,a,b,c,d,e)=(a,b,c,d,e) TRIO_ARGS6(z,a,b,c,d,e,f)=(a,b,c,d,e,f) TRIO_VARGS2(z,a,b)=(a,b) TRIO_VARGS3(z,a,b,c)=(a,b,c) TRIO_VARGS4(z,a,b,c,d)=(a,b,c,d) TRIO_VARGS5(z,a,b,c,d,e)=(a,b,c,d,e)
+
+# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line and do not end with a semicolon. Such function macros are typically
+# used for boiler-plate code, and will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tagfiles.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in Html, RTF and LaTeX) for classes with base or
+# super classes. Setting the tag to NO turns the diagrams off. Note that this
+# option is superceded by the HAVE_DOT option below. This is only a fallback. It is
+# recommended to install and use dot, since it yield more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found on the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_WIDTH = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT = 1024
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermedate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
+
+# The CGI_NAME tag should be the name of the CGI script that
+# starts the search engine (doxysearch) with the correct parameters.
+# A script with this name will be generated by doxygen.
+
+CGI_NAME =
+
+# The CGI_URL tag should be the absolute URL to the directory where the
+# cgi binaries are located. See the documentation of your http daemon for
+# details.
+
+CGI_URL =
+
+# The DOC_URL tag should be the absolute URL to the directory where the
+# documentation is located. If left blank the absolute path to the
+# documentation, with file:// prepended to it, will be used.
+
+DOC_URL =
+
+# The DOC_ABSPATH tag should be the absolute path to the directory where the
+# documentation is located. If left blank the directory on the local machine
+# will be used.
+
+DOC_ABSPATH =
+
+# The BIN_ABSPATH tag must point to the directory where the doxysearch binary
+# is installed.
+
+BIN_ABSPATH =
+
+# The EXT_DOC_PATHS tag can be used to specify one or more paths to
+# documentation generated for other projects. This allows doxysearch to search
+# the documentation for these projects as well.
+
+EXT_DOC_PATHS =
diff --git a/trio/doc/trio.css b/trio/doc/trio.css
new file mode 100644
index 00000000..1b3a9926
--- /dev/null
+++ b/trio/doc/trio.css
@@ -0,0 +1,35 @@
+/* HTML tags */
+
+BODY {
+ background-color: white;
+ color: darkblue;
+}
+
+TD { color: darkblue; }
+
+H1 { text-align: center; }
+
+H3 { font-style: italic; }
+
+HR {
+ width: 85%;
+ align: center;
+}
+
+.copyright { color: darkblue; }
+
+/* Links */
+
+:link { color: blue; }
+
+:visited { color: purple; }
+
+:active { color: red; }
+
+.el:link { font-style: italic; }
+
+/* Examples */
+
+DIV.fragment {
+ color: maroon;
+}
diff --git a/trio/example.c b/trio/example.c
new file mode 100644
index 00000000..50a1bd2f
--- /dev/null
+++ b/trio/example.c
@@ -0,0 +1,594 @@
+/*************************************************************************
+ * For testing purposes
+ */
+
+#include <stdarg.h>
+#include <limits.h>
+#include <math.h>
+#include <unistd.h>
+#include <wchar.h>
+#include "triodef.h"
+#include "trionan.h"
+#include "strio.h"
+#include "trio.h"
+#undef printf
+
+#if !defined(USE_LONGLONG)
+# if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+# define USE_LONGLONG
+# elif defined(__SUNPRO_C)
+# define USE_LONGLONG
+# endif
+#endif
+
+#if defined(USE_LONGLONG)
+# define LONGLONG long long
+#else
+# define LONGLONG long
+#endif
+
+#if defined(TRIO_C99)
+# define LONGEST intmax_t
+#else
+# define LONGEST LONGLONG
+#endif
+
+static TRIO_CONST char rcsid[] = "@(#)$Id: example.c,v 1.9 2001/11/25 13:47:38 breese Exp $";
+
+/*************************************************************************
+ *
+ */
+void Dump
+TRIO_ARGS2((buffer, rc),
+ char *buffer,
+ int rc)
+{
+ if (rc < 0)
+ {
+ printf("Err = %d (%s), Pos = %d\n",
+ TRIO_ERROR_CODE(rc),
+ TRIO_ERROR_NAME(rc),
+ TRIO_ERROR_POSITION(rc));
+ }
+ else
+ printf("buffer[% 3d] = \"%s\"\n", rc, buffer);
+}
+
+/*************************************************************************
+ *
+ */
+int main(TRIO_NOARGS)
+{
+ char buffer[512];
+ int rc;
+ LONGLONG int dummy;
+ char *fool;
+ int num;
+ int num2;
+ int count;
+ double dnum, dnum2;
+ float fnum, fnum2;
+ trio_long_double_t ldnum;
+ char *end;
+ char text[256];
+ char ch;
+ int nerrors = 0;
+ void *p1;
+ char *p2;
+
+ printf("%s\n", rcsid);
+
+/* printf("%d %u %d %u\n", */
+/* INT_MAX, INT_MAX, UINT_MAX, UINT_MAX); */
+/* trio_printf("%d %u %d %u\n", */
+/* INT_MAX, INT_MAX, UINT_MAX, UINT_MAX); */
+/* printf("%d %u\n", INT_MIN, INT_MIN); */
+/* trio_printf("%d %u\n", INT_MIN, INT_MIN); */
+
+/* printf("%ld %lu %ld %lu\n", */
+/* INT_MAX, INT_MAX, UINT_MAX, UINT_MAX); */
+/* trio_printf("%ld %lu %ld %lu\n", */
+/* INT_MAX, INT_MAX, UINT_MAX, UINT_MAX); */
+/* printf("%ld %lu\n", INT_MIN, INT_MIN); */
+/* trio_printf("%ld %lu\n", INT_MIN, INT_MIN); */
+
+/* printf("%lld %llu %lld %llu\n", */
+/* INT_MAX, INT_MAX, UINT_MAX, UINT_MAX); */
+/* trio_printf("%lld %llu %lld %llu\n", */
+/* INT_MAX, INT_MAX, UINT_MAX, UINT_MAX); */
+/* printf("%lld %llu\n", INT_MIN, INT_MIN); */
+/* trio_printf("%lld %llu\n", INT_MIN, INT_MIN); */
+
+/* return 0; */
+
+
+/* dnum = StrToDouble("3.14e+44", (const char **)&end); */
+/* printf("double = %e (%s)\n", dnum, end); */
+/* dnum = StrToDouble("0xA3.14p44", (const char **)&end); */
+/* printf("double = %e (%s)\n", dnum, end); */
+
+ /* trio_printf("%.*stext\n", 0, "-----"); */ /* fails */
+
+/* trio_printf("%Zd\n", (size_t)sizeof(char)); */
+
+/* rc = StrFormat(buffer, "%a", 3.14e+44); */
+/* Dump(buffer, rc); */
+
+ /* rc = StrFormat(buffer, "Filled string: %-16<fill=_>s", "test"); */
+
+/* errno = EINTR; */
+/* rc = StrFormat(buffer, "Error: %m"); */
+
+/* rc = StrFormat(buffer, "Count %lln", &dummy); */
+/* printf("dummy = %lld\n", dummy); */
+
+/* rc = StrFormat(buffer, "Char %<quote='>c", 'X'); */
+
+/* rc = StrFormatMax(buffer, 20, "Here goes %-20<adjust=_>s", "test"); */
+
+/* rc = StrFormat(buffer, "Hex-float %a", 3.1415); */
+/* Dump(buffer, rc); */
+/* rc = StrFormat(buffer, "Hex-float %A", 3.1415e20); */
+/* Dump(buffer, rc); */
+/* rc = StrFormat(buffer, "Double %#g", 3.1415e20); */
+/* Dump(buffer, rc); */
+/* rc = StrFormat(buffer, "Double %.3f", 3.1415); */
+/* Dump(buffer, rc); */
+/* rc = StrFormat(buffer, "Double %+e", 3.1415); */
+/* Dump(buffer, rc); */
+
+/* printf("'%.2f'\n", 99.99999); */
+/* trio_printf("'%.2f'\n", 99.99999); */
+/* printf("'%f'\n", 0.0); */
+/* trio_printf("'%f'\n", 0.0); */
+/* printf("'%f'\n", 3141.0); */
+/* trio_printf("'%f'\n", 3141.0); */
+/* printf("'%#f'\n", 3141.0); */
+/* trio_printf("'%#f'\n", 3141.0); */
+/* printf("'%'f'\n", 31415.2); */
+/* trio_printf("'%'f'\n", 31415.2); */
+/* printf("'%-16e'\n", 3141.5); */
+/* trio_printf("'%-16e'\n", 3141.5); */
+/* printf("'%#f'\n", 3141.0); */
+/* trio_printf("'%#f'\n", 3141.0); */
+/* printf("'%f'\n", 3141.5); */
+/* trio_printf("'%f'\n", 3141.5); */
+/* printf("'%#.6g'\n", 3141.5); */
+/* trio_printf("'%#.6g'\n", 3141.5); */
+
+/* printf("'%20e'\n", 314.5); */
+/* trio_printf("'%20e'\n", 314.5); */
+
+/* printf("'%-16e'\n", 3141.5); */
+/* trio_printf("'%-16e'\n", 3141.5); */
+
+/* printf("'%#.4g'\n", 314151.5); */
+/* trio_printf("'%#.4g'\n", 314151.5); */
+
+/* printf("'%#.4g'\n", 0.0); */
+/* trio_printf("'%#.4g'\n", 0.0); */
+
+/* printf("'%#.4g'\n", 11.0); */
+/* trio_printf("'%#.4g'\n", 11.0); */
+
+/* printf("%f\n", HUGE_VAL); */
+/* trio_printf("%f\n", HUGE_VAL); */
+/* printf("%f\n", -HUGE_VAL); */
+/* trio_printf("%f\n", -HUGE_VAL); */
+/* #define NAN (cos(HUGE_VAL)) */
+/* printf("%f\n", NAN); */
+/* trio_printf("%f\n", NAN); */
+
+/* printf("'%+06d'\n", 1234); */
+/* trio_printf("'%+06d'\n", 1234); */
+/* printf("'%-#6.3x'\n", 12); */
+/* trio_printf("'%-#06.3x'\n", 12); */
+/* printf("'%+6d'\n", 1234); */
+/* trio_printf("'%+6d'\n", 1234); */
+/* printf("'%-08d'\n", 12); */
+/* trio_printf("'%-08d'\n", 12); */
+/* printf("'%08.6d'\n", 12); */
+/* trio_printf("'%08.6d'\n", 12); */
+/* printf("'%4d'\n", 123456); */
+/* trio_printf("'%4d'\n", 123456); */
+/* printf("'%.4d'\n", 12); */
+/* trio_printf("'%.4d'\n", 12); */
+
+/* trio_printf("%!#08x %04x %..10x\n", 42, 42, 42); */
+/* trio_printf("%*.*.*i\n", 8, 4, 2, 23); */
+/* trio_printf("%8.4.2i %<base=2>08i %.8.2i %..2i\n", 23, 23, 23, 23); */
+
+/* trio_printf("%8i\n", 42); */
+/* trio_printf("%.7i\n", 42); */
+/* trio_printf("%..2i\n", 42); */
+/* trio_printf("%8.7i\n", 42); */
+/* trio_printf("%8..2i\n", 42); */
+/* trio_printf("%8.7.2i\n", 42); */
+/* trio_printf("%*.*.*i\n", 8, 7, 2, 42); */
+
+/* { */
+/* LONGLONG ll = 1234567890; */
+/* rc = trio_printf("%&i %d\n", sizeof(ll), ll, 42); */
+/* Dump(buffer, rc); */
+/* } */
+/* { */
+/* char ch = 12; */
+/* rc = trio_printf("%&i %d\n", sizeof(ch), ch, 42); */
+/* Dump(buffer, rc); */
+/* } */
+/* { */
+/* pid_t pid = 99; */
+/* rc = trio_printf("%&i %d\n", sizeof(pid), pid, 42); */
+/* Dump(buffer, rc); */
+/* } */
+
+/* rc = trio_printf("%*.*.*i\n", 6, 4, 10, 12); */
+/* Dump(buffer, rc); */
+/* rc = trio_printf("%1$0*3$.*2$d\n", 3141, 6, 10); */
+/* Dump(buffer, rc); */
+
+/* rc = trio_asprintf(&end, "%s%n", "0123456789", &num); */
+/* printf("%d %d '%s'\n", rc, num, end); */
+/* if (end) */
+/* free(end); */
+
+/* trio_printf("%016e\n", 3141.5); */
+/* trio_printf("%'f\n", 424242.42); */
+/* trio_printf("%#.4f\n", 0.0); */
+/* trio_printf("%'d\n", 424242); */
+
+/* rc = trio_sprintf(buffer, "%4$d %3$*8$d %2$.*7$d %1$*6$.*5$d\n", */
+/* 123, */
+/* 1234, */
+/* 12345, */
+/* 123456, */
+/* 5, 6, 7, 8 */
+/* ); */
+/* Dump(buffer, rc); */
+/* rc = trio_sprintf(buffer, "%2$s %1$#s", "111", "222"); */
+/* Dump(buffer, rc); */
+
+/* trio_printf(" %x %!#x %g %09x %x\n", 123456, 123456, 123456.0, 123456, 123456); */
+/* trio_printf("%!'i %f %i\n", 12345, 12345.0, 12345); */
+/* trio_printf("%!<base=2>i %i\n", 23, 23); */
+
+/* rc = trio_sprintf(buffer, "%I32d", 12345); */
+/* Dump(buffer, rc); */
+/* rc = trio_sprintf(buffer, "%I32I8d", 12345); */
+/* Dump(buffer, rc); */
+
+/* rc = trio_sprintf(buffer, "*%5f*", 3.3); */
+/* Dump(buffer, rc); */
+
+/* { */
+/* wchar_t *wstring = L"some data"; */
+/* wchar_t wbuffer[512]; */
+
+/* rc = trio_sprintf(buffer, "%ls", wstring); */
+/* Dump(buffer, rc); */
+
+/* rc = trio_sscanf(buffer, "%ls", wbuffer); */
+/* Dump(buffer, rc); */
+/* rc = trio_sprintf(buffer, "%ls", wbuffer); */
+/* Dump(buffer, rc); */
+/* } */
+
+ /* rc = StrFormat(buffer, "\040-\040\040-\n"); */
+
+/* rc = StrFormat(buffer, "%.*s@%s", 3, "Daniel", "Fool"); */
+/* rc = StrFormatAppendMax(buffer, 512, " %s is a doh", "Simpson"); */
+
+/* rc = StrFormat(buffer, "hello %1$d %1$d", 31, 32); */
+/* Dump(buffer, rc); */
+/* rc = StrFormat(buffer, "%2$d %3$d", 31, 32, 33); */
+/* Dump(buffer, rc); */
+
+/* rc = trio_sprintf(buffer, "%d say %g hey %s", 42, 3.14, "text"); */
+/* Dump(buffer, rc); */
+/* trio_sscanf(buffer, "%d %*s %e hey %s", &num, &dnum, text); */
+/* printf("num = %d, dnum = %e, text = \"%s\"\n", num, dnum, text); */
+
+/* rc = trio_sprintf(buffer, "%g", HUGE_VAL); */
+/* Dump(buffer, rc); */
+/* trio_sscanf(buffer, "%f", &dnum); */
+/* printf("dnum = %e\n", dnum); */
+
+/* rc = trio_sprintf(buffer, "%g", -HUGE_VAL); */
+/* Dump(buffer, rc); */
+/* trio_sscanf(buffer, "%f", &dnum); */
+/* printf("dnum = %e\n", dnum); */
+
+/* #if defined(NAN) */
+/* rc = trio_sprintf(buffer, "%g", NAN); */
+/* Dump(buffer, rc); */
+/* if ((rc = trio_sscanf(buffer, "%f", &dnum)) < 0) */
+/* Dump(buffer, rc); */
+/* else */
+/* printf("dnum = %e\n", dnum); */
+/* #endif */
+
+/* rc = trio_sprintf(buffer, "%*d", 6, 1234); */
+/* Dump(buffer, rc); */
+
+/* rc = trio_sprintf(buffer, "'%!08.6d' '%!d' '%d'", 4, 6, 8); */
+/* Dump(buffer, rc); */
+
+/* rc = trio_sprintf(buffer, "%0g", 0.123); */
+/* Dump(buffer, rc); */
+
+/* { */
+/* void *argarray[4]; */
+/* int value = 42; */
+/* double number = 123.456; */
+/* float small_number = 123.456; */
+
+/* argarray[0] = &value; */
+/* argarray[1] = "my string"; */
+/* rc = trio_sprintfv(buffer, "%d %s", argarray); */
+/* Dump(buffer, rc); */
+/* rc = trio_snprintfv(buffer, 8, "%d %s", argarray); */
+/* Dump(buffer, rc); */
+
+/* argarray[0] = &num; */
+/* argarray[1] = text; */
+/* rc = trio_sscanfv(buffer, "%d %s", argarray); */
+/* Dump(buffer, rc); */
+/* printf("num = %d text = \"%s\"\n", num, text); */
+
+/* argarray[0] = &number; */
+/* argarray[1] = &small_number; */
+/* rc = trio_sprintfv(buffer, "%f %hf", argarray); */
+/* Dump(buffer, rc); */
+/* printf("number = %f small_number = \"%f\"\n", number, small_number); */
+/* } */
+
+/* rc = trio_sprintf(buffer, "abcba"); */
+/* Dump(buffer, rc); */
+/* trio_sscanf(buffer, "%[ab]", text); */
+/* printf("text = \"%s\"\n", text); */
+/* trio_sscanf(buffer, "%*[ab]c%[^\n]", text); */
+/* printf("text = \"%s\"\n", text); */
+
+/* trio_sprintf(buffer, "aabcdba aaa"); */
+/* rc = trio_sscanf(buffer, "%s", text); */
+/* Dump(buffer, rc); */
+/* printf("text = \"%s\"\n", text); */
+/* rc = trio_sscanf(buffer, "%*1[aA]%[a-c]", text); */
+/* Dump(buffer, rc); */
+/* printf("text = \"%s\"\n", text); */
+
+/* rc = trio_sprintf(buffer, "10021"); */
+/* rc = trio_sscanf(buffer, "%b%n%d", &num, &count, &num2); */
+/* Dump(buffer, rc); */
+/* printf("num = %d %d %d\n", num, num2, count); */
+
+/* rc = trio_sprintf(buffer, "%'d", 10000); */
+/* rc = trio_sscanf(buffer, "%'d", &num); */
+/* Dump(buffer, rc); */
+/* printf("num = %d\n", num); */
+
+/* rc = trio_dprintf(STDOUT_FILENO, "%s\n", "hello there"); */
+/* Dump(buffer, rc); */
+/* rc = trio_dscanf(STDIN_FILENO, "%s", buffer); */
+/* Dump(buffer, rc); */
+
+/* rc = trio_scanf("%s", buffer); */
+/* Dump(buffer, rc); */
+
+/* rc = trio_sprintf(buffer, "Ttext"); */
+/* Dump(buffer, rc); */
+/* trio_sscanf(buffer, "%*[Tt]e%c", &ch); */
+/* printf("ch = %c\n", ch); */
+
+/* printf("%p\n", &main); */
+/* rc = trio_sprintf(buffer, "%p %p", &main, NULL); */
+/* Dump(buffer, rc); */
+/* trio_sscanf(buffer, "%p %p", &p1, &p2); */
+/* printf("pointer = %p %p\n", p1, p2); */
+
+/* rc = trio_sprintf(buffer, "%@.@.@i", 8, 7, 2, 42); */
+/* Dump(buffer, rc); */
+/* trio_sprintf(buffer, "abcdefghijklmnopqrstuvwxyz"); */
+/* rc = trio_sscanf(buffer, "%100s", text); */
+/* Dump(text, rc); */
+/* rc = trio_sscanf(buffer, "%@s", 100, text); */
+/* Dump(text, rc); */
+
+/* rc = trio_sprintf(buffer, "%..2i", 42); */
+/* Dump(buffer, rc); */
+/* rc = trio_sscanf(buffer, "%..2i", &num); */
+/* printf("%d\n", num); */
+/* rc = trio_sscanf(buffer, "%..@i", 2, &num); */
+/* printf("%d\n", num); */
+
+/* { */
+/* int num1, num2, num3, num4; */
+
+/* rc = trio_sprintf(buffer, "123_456 [12%%-34%%]"); */
+/* Dump(buffer, rc); */
+/* rc = trio_sscanf(buffer, "%5i%*1s%5i%*1s%5i%*2s%5i", */
+/* &num1, &num2, &num3, &num4); */
+/* Dump(buffer, rc); */
+/* printf("%d %d %d %d %d\n", rc, num1, num2, num3, num4); */
+/* rc = trio_sscanf(buffer, "%d_%d [%d%%-%d%%]", */
+/* &num1, &num2, &num3, &num4); */
+/* Dump(buffer, rc); */
+/* printf("%d %d %d %d %d\n", rc, num1, num2, num3, num4); */
+/* } */
+
+/* rc = trio_sprintf(buffer, "01 3456789"); */
+/* Dump(buffer, rc); */
+/* memset(&text, 0, sizeof(text)); */
+/* rc = trio_sscanf(buffer, "%4c", &text); */
+/* Dump(text, rc); */
+/* memset(&text, 0, sizeof(text)); */
+/* rc = sscanf(buffer, "%4c", &text); */
+/* Dump(text, rc); */
+
+/* rc = trio_sprintf(buffer, "12345 6"); */
+/* Dump(buffer, rc); */
+/* rc = trio_sscanf(buffer, "%2d", &num); */
+/* Dump(buffer, rc); */
+/* printf("%d\n", num); */
+/* rc = sscanf(buffer, "%2d", &num); */
+/* Dump(buffer, rc); */
+/* printf("%d\n", num); */
+
+/* rc = trio_sprintf(buffer, "aa\\x0abb"); */
+/* Dump(buffer, rc); */
+/* rc = trio_sscanf(buffer, "aa%#sbb", &text); */
+/* Dump(text, rc); */
+
+/* rc = trio_sscanf("0 ", "%f", &dnum, text); */
+/* printf("%d %f\n", rc, dnum); */
+/* rc = sscanf("0 ", "%f %s", &dnum, text); */
+/* printf("%d %f\n", rc, dnum); */
+
+/* rc = trio_sscanf("lære", "%[:alpha:]", text); */
+/* Dump(text, rc); */
+
+/* rc = trio_sscanf("-0.123e3", "%8e", &dnum); */
+/* printf("%d %f\n", rc, dnum); */
+
+/* rc = trio_sscanf("123,456.78", "%'f", &dnum); */
+/* printf("%d %f\n", rc, dnum); */
+
+/* trio_printf("%.24f\n%.24f\n%.24f\n", 39413.80, 1.4, (2.0/3.0)); */
+/* printf("%.24f\n%.24f\n%.24f\n", 39413.80, 1.4, (2.0/3.0)); */
+
+/* trio_printf("%f\n%f\n", (7.0/5.0), (2.0/3.0)); */
+/* printf("%f\n%f\n", (7.0/5.0), (2.0/3.0)); */
+
+/* trio_printf("%a\n", 42.0); */
+/* trio_printf("%.2e\n", 0.9999); */
+/* trio_printf("%e\n", 3.14e+123); */
+/* trio_printf("%010.3e\n", 3141.5); */
+/* trio_printf("%.32Rf\n", 1.4); */
+/* trio_printf("%Rf\n", 1.234567890123456789e20); */
+/* printf("%.2g\n", 0.9999); */
+/* trio_printf("%.2g\n", 0.9999); */
+/* printf("%.2g\n", 99.9999); */
+/* trio_printf("%.2g\n", 99.9999); */
+/* printf("%g\n", 0.0); */
+/* trio_printf("%g\n", 0.0); */
+/* printf("%f\n", 3141.0); */
+/* trio_printf("%f\n", 3141.0); */
+/* printf("%.0f\n", 3141.0); */
+/* trio_printf("%.0f\n", 3141.0); */
+/* trio_printf("%f\n", 2.0/3.0); */
+/* trio_printf("%f\n", 16.25); */
+
+/* trio_printf("A: %f\nB: %.20f\nC: %Rf\n", 0.1, 0.1, 0.1); */
+/* trio_printf("A: %f\nB: %.20f\nC: %Rf\n", 2.0/3.0, 2.0/3.0, 2.0/3.0); */
+
+/* trio_printf("R %.*Rhf\n", FLT_DIG + 4, (double)((float)1.4)); */
+/* trio_printf("T %.*hf\n", FLT_DIG + 4, (double)((float)(2.0/3.0))); */
+/* trio_printf("R %.*Rhf\n", FLT_DIG + 4, (double)((float)(2.0/3.0))); */
+
+/* trio_printf("T %.*f\n", DBL_DIG + 4, (2.0/3.0)); */
+/* trio_printf("R %.*Rf\n", DBL_DIG + 4, (2.0/3.0)); */
+/* printf("C %.*f\n", DBL_DIG + 4, (2.0/3.0)); */
+
+/* trio_printf("T %.*f\n", DBL_DIG + 4, 1.4); */
+/* trio_printf("R %.*Rf\n", DBL_DIG + 4, 1.4); */
+/* printf("C %.*f\n", DBL_DIG + 4, 1.4); */
+
+/* trio_printf("T %.*f\n", DBL_DIG + 6, 0.1); */
+/* trio_printf("R %.*Rf\n", DBL_DIG + 6, 0.1); */
+/* printf("C %.*f\n", DBL_DIG + 6, 0.1); */
+
+/* ldnum = 2.0L / 3.0L; */
+/* trio_printf("R %.*Lf\n", LDBL_DIG + 4, ldnum); */
+/* trio_printf("R %RLf\n", ldnum); */
+
+/* trio_printf("T %.*.2f\n", DBL_MANT_DIG, 1.4); */
+/* trio_printf("R %.*.2Rf\n", DBL_MANT_DIG, 1.4); */
+
+/* trio_printf("R %Rf\n", 1.234567890123456789e20); */
+/* trio_printf("T %10.3e\n", 3141.5); */
+/* trio_printf("T %f\n", 1.0/3.0); */
+
+ /* 2^-1 + 2^-15 */
+/* trio_printf("T %.*g\n", DBL_DIG + 200, 0.500030517578125); */
+/* printf("C %.*g\n", DBL_DIG + 200, 0.500030517578125); */
+/* trio_printf("T %.*g\n", DBL_DIG + 200, 2.0/3.0); */
+/* printf("C %.*g\n", DBL_DIG + 200, 2.0/3.0); */
+
+/* trio_printf("T %.*f\n", DBL_DIG + 2, 1.4); */
+/* trio_printf("TR %.*Rf\n", DBL_DIG + 2, 1.4); */
+
+/* rc = trio_sscanf("0.141882295971771490", "%Lf", &ldnum); */
+/* rc = trio_sprintf(buffer, "%.30Lf", ldnum); */
+/* Dump(buffer, rc); */
+
+/* ldnum = 1.0L; */
+/* ldnum /= 3.0L; */
+/* rc = trio_sprintf(buffer, "%.30Lf", ldnum); */
+/* Dump(buffer, rc); */
+
+/* { */
+/* float a = 5.9, b = 10.0, c = a * b; */
+/* double d = a * b; */
+/* trio_printf("%.15a %.15a\n", c, d); */
+/* trio_printf("%.15g %.15g\n", c, (float)(a * b)); */
+/* trio_printf("%.15a %.15a\n", c, (float)(a * b)); */
+/* trio_printf("%.30.2f %.30.2f\n", c, (float)(a * b)); */
+/* } */
+
+/* trio_locale_set_decimal_point(","); */
+/* trio_locale_set_thousand_separator("'"); */
+/* trio_locale_set_grouping("\1\3\2\177"); */
+/* trio_printf("%'d\n", 123456789); */
+/* trio_printf("%'f\n", 123456789.0); */
+/* trio_locale_set_grouping("\3\2\0"); */
+/* trio_printf("%'d\n", 123456789); */
+/* trio_printf("%'f\n", 123456789.0); */
+
+/* trio_printf("%.30Rf\n", 39413.80); */
+
+/* printf("% 10.5f\n", 5163723399.00000); */
+/* trio_printf("% 10.5f\n", 5163723399.00000); */
+
+/* printf("% 020.5f\n", 5163723399.00000); */
+/* trio_printf("% 020.5f\n", 5163723399.00000); */
+
+/* rc = trio_vsnprintf(buffer, 8, "printing\n", NULL); */
+/* Dump(buffer, rc); */
+
+/* rc = trio_sprintf(buffer, "%.o %#.o", 0, 0); */
+/* Dump(buffer, rc); */
+/* rc = trio_sprintf(buffer, "%8.o %08.4o", 0, 0); */
+/* Dump(buffer, rc); */
+/* rc = trio_sprintf(buffer, "%8o %08o", 0, 0); */
+/* Dump(buffer, rc); */
+
+/* rc = trio_sprintf(buffer, "%a %a", 0.0, 1.0); */
+/* Dump(buffer, rc); */
+
+/* printf("%*s%*s%*s\n", */
+/* -1, "one", */
+/* -20, "two", */
+/* -30,"three"); */
+/* trio_printf("%*s%*s%*s\n", */
+/* -1, "one", */
+/* -20, "two", */
+/* -30,"three"); */
+
+/* dnum = pow (2.0, -1024.1); */
+/* dnum = pow (2.0, -1024); */
+/* dnum = pow(2.0, 16.0); */
+/* rc = trio_snprintf(buffer, sizeof(buffer), "%.200g %a %.200.2g", */
+/* dnum, dnum, dnum); */
+/* Dump(buffer, rc); */
+
+/* dnum = 3.141e-44; */
+/* rc = trio_snprintf(buffer, sizeof(buffer), "%.200g %a %.200.2g", */
+/* dnum, dnum, dnum); */
+/* Dump(buffer, rc); */
+
+ rc = trio_sscanf("0x2.ap+4", "%a", &dnum);
+ trio_snprintf(buffer, sizeof(buffer), "%f %a", dnum, dnum);
+ Dump(buffer, rc);
+
+ return 0;
+}
diff --git a/trio/html/group___dynamic_strings.html b/trio/html/group___dynamic_strings.html
new file mode 100644
index 00000000..ab349297
--- /dev/null
+++ b/trio/html/group___dynamic_strings.html
@@ -0,0 +1,362 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+ <title>TRIO</title>
+ <link href="trio.css" rel="stylesheet" type="text/css">
+</head>
+<body>
+<!-- Generated by Doxygen 1.2.12 -->
+<center>
+<a class="qindex" href="index.html">Main Page</a> &nbsp; <a class="qindex" href="modules.html">Modules</a> &nbsp; </center>
+<hr><h1>Dynamic String Functions.</h1>Dynamic string functions.
+<a href="#_details">More...</a><table border=0 cellpadding=0 cellspacing=0>
+<tr><td colspan=2><br><h2>Functions</h2></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC trio_string_t *&nbsp;</td><td valign=bottom><a class="el" href="group___dynamic_strings.html#a3">trio_string_create</a> (int initial_size)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Create a new dynamic string.</em> <a href="#a3">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC void&nbsp;</td><td valign=bottom><a class="el" href="group___dynamic_strings.html#a4">trio_string_destroy</a> (trio_string_t *self)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Deallocate the dynamic string and its contents.</em> <a href="#a4">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC char *&nbsp;</td><td valign=bottom><a class="el" href="group___dynamic_strings.html#a5">trio_string_get</a> (trio_string_t *self, int offset)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Get a pointer to the content.</em> <a href="#a5">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC char *&nbsp;</td><td valign=bottom><a class="el" href="group___dynamic_strings.html#a6">trio_string_extract</a> (trio_string_t *self)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Extract the content.</em> <a href="#a6">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC void&nbsp;</td><td valign=bottom><a class="el" href="group___dynamic_strings.html#a7">trio_xstring_set</a> (trio_string_t *self, char *buffer)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Set the content of the dynamic string.</em> <a href="#a7">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC int&nbsp;</td><td valign=bottom><a class="el" href="group___dynamic_strings.html#a10">trio_string_append</a> (trio_string_t *self, trio_string_t *other)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Append the second string to the first.</em> <a href="#a10">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC int&nbsp;</td><td valign=bottom><a class="el" href="group___dynamic_strings.html#a13">trio_string_contains</a> (trio_string_t *self, trio_string_t *other)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Search for the first occurrence of second parameter in the first.</em> <a href="#a13">More...</a><em></em></font><br><br></td></tr>
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+Dynamic string functions.
+<p>
+<b>SYNOPSIS</b>
+<p>
+<div class="fragment"><pre>
+cc ... -ltrio -lm
+
+#include &lt;triostr.h&gt;
+</pre></div>
+<p>
+<b>DESCRIPTION</b> <hr><h2>Function Documentation</h2>
+<a name="a10" doxytag="triostr.c::trio_string_append"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC int trio_string_append </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">trio_string_t *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>self</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>trio_string_t *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>other</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Append the second string to the first.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>self</em>&nbsp;</td><td>
+Dynamic string to be modified. </td></tr>
+<tr><td valign=top><em>other</em>&nbsp;</td><td>
+Dynamic string to copy from. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Boolean value indicating success or failure. </dl> </td>
+ </tr>
+</table>
+<a name="a13" doxytag="triostr.c::trio_string_contains"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC int trio_string_contains </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">trio_string_t *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>self</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>trio_string_t *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>other</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Search for the first occurrence of second parameter in the first.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>self</em>&nbsp;</td><td>
+Dynamic string to be modified. </td></tr>
+<tr><td valign=top><em>other</em>&nbsp;</td><td>
+Dynamic string to copy from. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Boolean value indicating success or failure. </dl> </td>
+ </tr>
+</table>
+<a name="a3" doxytag="triostr.c::trio_string_create"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC trio_string_t* trio_string_create </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">int&nbsp;</td>
+ <td class="mdname1" valign="top" nowrap>&nbsp; <em>initial_size</em> </td>
+ <td class="md" valign="top">)&nbsp;</td>
+ <td class="md" nowrap></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Create a new dynamic string.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>initial_size</em>&nbsp;</td><td>
+Initial size of the buffer. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Newly allocated dynamic string, or NULL if memory allocation failed. </dl> </td>
+ </tr>
+</table>
+<a name="a4" doxytag="triostr.c::trio_string_destroy"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC void trio_string_destroy </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">trio_string_t *&nbsp;</td>
+ <td class="mdname1" valign="top" nowrap>&nbsp; <em>self</em> </td>
+ <td class="md" valign="top">)&nbsp;</td>
+ <td class="md" nowrap></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Deallocate the dynamic string and its contents.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>self</em>&nbsp;</td><td>
+Dynamic string </td></tr>
+</table>
+</dl> </td>
+ </tr>
+</table>
+<a name="a6" doxytag="triostr.c::trio_string_extract"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC char* trio_string_extract </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">trio_string_t *&nbsp;</td>
+ <td class="mdname1" valign="top" nowrap>&nbsp; <em>self</em> </td>
+ <td class="md" valign="top">)&nbsp;</td>
+ <td class="md" nowrap></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Extract the content.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>self</em>&nbsp;</td><td>
+Dynamic String </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Content of dynamic string.</dl>The content is removed from the dynamic string. This enables destruction of the dynamic string without deallocation of the content. </td>
+ </tr>
+</table>
+<a name="a5" doxytag="triostr.c::trio_string_get"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC char* trio_string_get </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">trio_string_t *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>self</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>int&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>offset</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Get a pointer to the content.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>self</em>&nbsp;</td><td>
+Dynamic string. </td></tr>
+<tr><td valign=top><em>offset</em>&nbsp;</td><td>
+Offset into content. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Pointer to the content.</dl><code>Offset</code> can be zero, positive, or negative. If <code>offset</code> is zero, then the start of the content will be returned. If <code>offset</code> is positive, then a pointer to <code>offset</code> number of characters from the beginning of the content is returned. If <code>offset</code> is negative, then a pointer to <code>offset</code> number of characters from the ending of the string, starting at the terminating zero, is returned. </td>
+ </tr>
+</table>
+<a name="a7" doxytag="triostr.c::trio_xstring_set"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC void trio_xstring_set </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">trio_string_t *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>self</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>buffer</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Set the content of the dynamic string.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>self</em>&nbsp;</td><td>
+Dynamic String </td></tr>
+<tr><td valign=top><em>buffer</em>&nbsp;</td><td>
+The new content.</td></tr>
+</table>
+</dl>Sets the content of the dynamic string to a copy <code>buffer</code>. An existing content will be deallocated first, if necessary.
+<p>
+<dl compact><dt><b>
+Remarks: </b><dd>
+ This function will make a copy of <code>buffer</code>. You are responsible for deallocating <code>buffer</code> yourself. </dl> </td>
+ </tr>
+</table>
+<HR>
+<center class="copyright">Copyright (C) 2001 Bj&oslash;rn Reese and Daniel Stenberg.</center>
+</body>
+</html>
diff --git a/trio/html/group___printf.html b/trio/html/group___printf.html
new file mode 100644
index 00000000..7f79200f
--- /dev/null
+++ b/trio/html/group___printf.html
@@ -0,0 +1,1259 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+ <title>TRIO</title>
+ <link href="trio.css" rel="stylesheet" type="text/css">
+</head>
+<body>
+<!-- Generated by Doxygen 1.2.12 -->
+<center>
+<a class="qindex" href="index.html">Main Page</a> &nbsp; <a class="qindex" href="modules.html">Modules</a> &nbsp; </center>
+<hr><h1>Formatted Printing Functions.</h1>Variations of formatted printing functions.
+<a href="#_details">More...</a><table border=0 cellpadding=0 cellspacing=0>
+<tr><td colspan=2><br><h2>Functions</h2></td></tr>
+<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a0">trio_printf</a> (const char *format,...)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Print to standard output stream.</em> <a href="#a0">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a1">trio_vprintf</a> (const char *format, va_list args)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Print to standard output stream.</em> <a href="#a1">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a2">trio_printfv</a> (const char *format, trio_pointer_t *args)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Print to standard output stream.</em> <a href="#a2">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a3">trio_fprintf</a> (FILE *file, const char *format,...)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Print to file.</em> <a href="#a3">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a4">trio_vfprintf</a> (FILE *file, const char *format, va_list args)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Print to file.</em> <a href="#a4">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a5">trio_fprintfv</a> (FILE *file, const char *format, trio_pointer_t *args)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Print to file.</em> <a href="#a5">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a6">trio_dprintf</a> (int fd, const char *format,...)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Print to file descriptor.</em> <a href="#a6">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a7">trio_vdprintf</a> (int fd, const char *format, va_list args)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Print to file descriptor.</em> <a href="#a7">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a8">trio_dprintfv</a> (int fd, const char *format, trio_pointer_t *args)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Print to file descriptor.</em> <a href="#a8">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a12">trio_sprintf</a> (char *buffer, const char *format,...)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Print to string.</em> <a href="#a12">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a13">trio_vsprintf</a> (char *buffer, const char *format, va_list args)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Print to string.</em> <a href="#a13">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a14">trio_sprintfv</a> (char *buffer, const char *format, trio_pointer_t *args)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Print to string.</em> <a href="#a14">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a15">trio_snprintf</a> (char *buffer, size_t max, const char *format,...)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Print at most <code>max</code> characters to string.</em> <a href="#a15">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a16">trio_vsnprintf</a> (char *buffer, size_t max, const char *format, va_list args)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Print at most <code>max</code> characters to string.</em> <a href="#a16">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___printf.html#a17">trio_snprintfv</a> (char *buffer, size_t max, const char *format, trio_pointer_t *args)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Print at most <code>max</code> characters to string.</em> <a href="#a17">More...</a><em></em></font><br><br></td></tr>
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+Variations of formatted printing functions.
+<p>
+<b>SYNOPSIS</b>
+<p>
+<div class="fragment"><pre>
+cc ... -ltrio -lm
+
+#include &lt;trio.h&gt;
+</pre></div>
+<p>
+<b>DESCRIPTION</b>
+<p>
+This documentation is incomplete. The documentation of the printf family in [C99] and [UNIX98] also applies to the trio counterparts.
+<p>
+All these functions outputs a string which is formatted according to the <code>format</code> string and the consecutive arguments. The <code>format</code> string is described in the Formatting section below.
+<p>
+<a class="el" href="group___printf.html#a0">trio_printf</a>, <a class="el" href="group___printf.html#a1">trio_vprintf</a>, and <a class="el" href="group___printf.html#a2">trio_printfv</a> writes the output to the standard output stream (stdout).
+<p>
+<a class="el" href="group___printf.html#a3">trio_fprintf</a>, <a class="el" href="group___printf.html#a4">trio_vfprintf</a>, and <a class="el" href="group___printf.html#a5">trio_fprintfv</a> writes the output to a given output stream.
+<p>
+<a class="el" href="group___printf.html#a6">trio_dprintf</a>, <a class="el" href="group___printf.html#a7">trio_vdprintf</a>, and <a class="el" href="group___printf.html#a8">trio_dprintfv</a> writes the output to a file descriptor (this includes, for example, sockets).
+<p>
+<a class="el" href="group___printf.html#a12">trio_sprintf</a>, <a class="el" href="group___printf.html#a13">trio_vsprintf</a>, and <a class="el" href="group___printf.html#a14">trio_sprintfv</a> writes the output into <code>buffer</code>.
+<p>
+<a class="el" href="group___printf.html#a15">trio_snprintf</a>, <a class="el" href="group___printf.html#a16">trio_vsnprintf</a>, and <a class="el" href="group___printf.html#a17">trio_snprintfv</a> writes <code>max</code> - 1 characters into <code>buffer</code> followed by a terminating zero character. If <code>max</code> is 1, then <code>buffer</code> will be an empty string. If <code>max</code> is 0, then <code>buffer</code> is left untouched, and can consequently be NULL. The number of characters that would have been written to <code>buffer</code>, had there been sufficient space, is returned.
+<p>
+trio_snprintfcat appends the formatted text at the end of <code>buffer</code>.
+<p>
+trio_asprintf and trio_vasprintf allocates and returns an allocated string in <code>buffer</code> containing the formatted text.
+<p>
+<b>FORMATTING</b>
+<p>
+The <code>format</code> string can contain normal text and conversion indicators. The normal text can be any character except the nil character (\000 = '\0') and the percent character (\045 = '%'). Conversion indicators consists of an indication character (%), followed by zero or more conversion modifiers, and exactly one conversion specifier.
+<p>
+<b>Modifiers</b>
+<p>
+Some modifiers exhibit the same behaviour for all specifiers, other modifiers indicate different behaviours for different specifiers, and other modifiers are only applicable to certain specifiers. The relationship is described for each modifier. The number 9 is used to denotes an arbitrary integer.
+<p>
+<em>Positional</em> ( <code>9$</code> ) [UNIX98]
+<p>
+Normally the arguments supplied to these functions are interpreted incrementially from left to right. Arguments can be referenced specifically in the format string. The modifier n$ selects the nth argument. The first argument is referred as 1$. If this modifier is used, it must be the first modifier after the indication character. n$ can also be used for argument width, precision, and base.
+<p>
+The performance penalty of using positionals is almost neglible (contrary to most other printf implementations).
+<p>
+<ul>
+<li> <em>Reference</em> <em>Mix</em>. Mixing normal and positional specifiers is allowed [TRIO]. For example, <div class="fragment"><pre>
+ trio_printf("%d %3$d %2$d\n", 1, 2, 3);
+</pre></div> results in <div class="fragment"><pre>
+ 1 3 2
+</pre></div> Arguments for the printf family are passed on the stack. On most platforms it is not possible to determine the size of individual stack elements, so it is essential that the format string corresponds exactly to the passed arguments. If this is not the case, incorrect values may be put into the result.</ul>
+<ul>
+<li> <em>Reference</em> <em>Gap</em>. For the same reason it is also essential that the format string does not contain any "gaps" in the positional arguments. For example, <div class="fragment"><pre>
+ trio_printf("%1$d %3$d\n", 1, 2, 3);
+</pre></div> is NOT allowed. The format string parser has no knowledge about whether the second argument is, say, an integer or a long double (which have different sizes). <div class="fragment"><pre>
+</pre></div> [UNIX98] describes this as unspecified behaviour. [TRIO] will detect reference gaps and return an error.</ul>
+<ul>
+<li> <em>Double</em> <em>Reference</em>. It is also not allowed to reference an argument twice or more. For example, <div class="fragment"><pre>
+ trio_printf("%1$d %1$lf\n", 1);
+</pre></div> is NOT allowed, because it references the first argument as two differently sized objects. <div class="fragment"><pre>
+</pre></div> [UNIX98] describes this as unspecified behaviour. [TRIO] will detect double references and return an error.</ul>
+The following two statements are equivalent <div class="fragment"><pre>
+ trio_printf("|%d %s\n|", 42, "meanings");
+ |42 meanings|
+
+ trio_printf("|%1$d %2$s|\n", 42, "meanings");
+ |42 meanings|
+</pre></div>
+<p>
+<em>Width</em> ( <code>9</code> )
+<p>
+Specifies the minimum width of a field. If the fields has less characters than specified by the width, the field will be left adjusted and padded by spaces. The adjustment and padding can be changed by the Alignment ( <code>-</code> ) and Padding ( <code>0</code> ) modifiers.
+<p>
+The width is specified as a number. If an asterix ( <code>*</code> ) is used instead, the width will be read from the argument list.
+<p>
+Prefixes, such as 0x for hexadecimal integers, are part of width. <div class="fragment"><pre>
+ trio_printf("|%10i|\n", 42);
+ | 42|
+</pre></div>
+<p>
+<em>Precision</em> ( .<code>9</code> )
+<p>
+The precision has different semantics for the various data types. The precision specifies the maximum number of printed characters for strings, the number of digits after the decimal-point for floating-point numbers, the number of significant digits for the <code>g</code> (and <code>G)</code> representation of floating-point numbers, the minimum number of printed digits for integers. <div class="fragment"><pre>
+ trio_printf("|%10.8i|%.8i|\n", 42, 42);
+ | 00000042|00000042|
+</pre></div>
+<p>
+<em>Base</em> ( ..<code>9</code> ) [TRIO]
+<p>
+Sets the base that the associated integer must be converted to. The base can be between 2 and 36 (both included). <div class="fragment"><pre>
+ trio_printf("|%10.8.2i|%10..2i|%..2i|\n", 42, 42, 42);
+ | 00101010| 101010|101010|
+
+ trio_printf("|%*.8.*i|\n", 10, 2, 42);
+ | 00101010|
+</pre></div>
+<p>
+<em>Padding</em> ( <code>0</code> )
+<p>
+Integer and floating point numbers are prepended by zeros. The number of leading zeros are determined by the precision. If precision is not present, width is used instead.
+<p>
+<em>Short</em> ( <code>h</code> )
+<p>
+Integer arguments are read as an ( <code>unsigned</code> ) <code>short</code> <code>int</code>. String and character arguments are read as <code>char</code> <code>*</code> and <code>char</code> respectively.
+<p>
+<em>Short</em> <em>short</em> ( <code>hh</code> ) [C99, GNU]
+<p>
+The argument is read as an ( <code>unsigned</code> ) <code>char</code>.
+<p>
+<em>Fixed</em> <em>Size</em> ( <code>I</code> ) [MSVC]
+<p>
+The argument is read as a fixed sized integer. The modifier is followed by a number, which specifies the number of bits in the integer, and can be one of the following
+<p>
+<ul>
+<li> <code>I8</code> <li> <code>I16</code> <li> <code>I32</code> <li> <code>I64</code> (if 64-bits integers are supported)</ul>
+Works only for integers (i, u, d, o, x, X)
+<p>
+<em>Largest</em> ( <code>j</code> ) [C99]
+<p>
+The argument is read as an <code>intmax_t</code> / <code>uintmax_t</code>, which is defined to be the largest signed/unsigned integer.
+<p>
+<em>Long</em> ( <code>l</code> )
+<p>
+An integral argument is read as an ( <code>unsigned</code> ) <code>long</code> <code>int</code>. A string argument is read as a <code>wchar_t</code> <code>*</code>, and output as a multi-byte character sequence.
+<p>
+<em>Long</em> <em>long</em> ( <code>ll</code> ) [C99, UNIX98, GNU]
+<p>
+The argument is read as an ( <code>unsigned</code> ) <code>long</code> <code>long</code> <code>int</code>.
+<p>
+<em>Long</em> <em>double</em> ( <code>L</code> ) [C99, UNIX98, GNU]
+<p>
+The argument is read as a <code>long</code> <code>double</code>.
+<p>
+<em>ptrdiff_t</em> ( <code>t</code> ) [C99]
+<p>
+The argument is read as a <code>ptrdiff_t</code>, which is defined to be the signed integer type of the result of subtracting two pointers.
+<p>
+<em>Quad</em> ( <code>q</code> ) [BSD, GNU]
+<p>
+Corresponds to the long long modifier ( <code>ll</code> ).
+<p>
+<em>Wide</em> ( <code>w</code> ) [MISC]
+<p>
+For a string argument this is equivalent to using the long modifier ( <code>l</code> ).
+<p>
+<em>size_t</em> ( <code>z</code> ) [C99]
+<p>
+The argument is read as a <code>size_t</code>, which is defined to be the type returned by the <code>sizeof</code> operator.
+<p>
+<em>size_t</em> ( <code>Z</code> ) [GNU]
+<p>
+Corresponds to the size_t modifier ( <code>z</code> ).
+<p>
+<em>Alternative</em> ( <code>#</code> )
+<p>
+Prepend radix indicator for hexadecimal, octal, and binary integer numbers and for pointers. Always add a decimal-pointer for floating-point numbers. Escape non-printable characters for strings.
+<p>
+<em>Spacing</em> ( )
+<p>
+Prepend leading spaces when necessary.
+<p>
+<em>Sign</em> ( <code>+</code> )
+<p>
+Always prepend a sign to numbers. Normally only the negative sign is prepended to a number. With this modifier the positive sign may also be prepended.
+<p>
+<em>Alignment</em> ( <code>-</code> )
+<p>
+The output will be left-justified in the field specified by the width.
+<p>
+<em>Argument</em> ( <code>*</code> )
+<p>
+Width, precision, or base is read from the argument list, rather than from the formatting string.
+<p>
+<em>Quote</em> / <em>Grouping</em> ( ' <code>)</code> [MISC]
+<p>
+Groups integers and the integer-part of floating-point numbers according to the locale. Quote strings and characters.
+<p>
+<em>Sticky</em> ( <code>!</code> ) [TRIO]
+<p>
+The modifiers listed for the current specifier will be reused by subsequent specifiers of the same group. The following specifier groups exists <ul>
+<li> Integer ( <code>i</code>, <code>u</code>, <code>d</code>, <code>o</code>, <code>x</code>, <code>X</code> ) <li> Floating-point ( <code>f</code>, <code>F</code>, <code>e</code>, <code>E</code>, <code>g</code>, <code>G</code>, <code>a</code>, <code>A</code> ) <li> Character ( <code>c</code> ) <li> String ( <code>s</code> ) <li> Pointer ( <code>p</code> ) <li> Count ( <code>n</code> ) <li> Errno ( <code>m</code> ) <li> Group ( <code>[]</code> )</ul>
+The sticky modifiers are active until superseeded by other sticky modifiers, or the end of the format string is reached. Local modifiers overrides sticky modifiers for the given specifier only. <div class="fragment"><pre>
+ trio_printf("|%!08#x|%04x|%x|\n", 42, 42, 42);
+ |0x00002a|0x2a|0x00002a|
+</pre></div>
+<p>
+<b>Specifiers</b>
+<p>
+<em>Percent</em> ( <code>%</code> )
+<p>
+Produce a percent ( <code>%</code> ) character. This is used to quote the indication character. No modifiers are allowed. The full syntax is <code>%%</code>. <div class="fragment"><pre>
+ trio_printf("Percent is %%\n");
+ Percent is %
+</pre></div>
+<p>
+<em>Hex</em> <em>floats</em> ( <code>a</code>, <code>A</code> ) [C99]
+<p>
+Output a hexadecimal (base 16) representation of a floating point number. The number is automatically preceeded by <code>0x</code> ( or <code>0X</code> ). The exponent is <code>p</code> ( or <code>P</code> ). <div class="fragment"><pre>
+ trio_printf("|%a|%A|\n", 3.1415, 3.1415e20);
+ |0x3.228bc|0X3.228BCP+14|
+</pre></div>
+<p>
+<em>Binary</em> <em>numbers</em> ( <code>b</code>, <code>B</code> ) [MISC - SCO UnixWare 7]
+<p>
+DEPRECATED: Use Base modifier <code>%..2i</code> instead.
+<p>
+<em>Character</em> ( <code>c</code> )
+<p>
+Output a single character.
+<p>
+<ul>
+<li> Quote ( ' <code>)</code> [TRIO]. Quote the character.</ul>
+<em>Decimal</em> ( <code>d</code> )
+<p>
+Output a decimal (base 10) representation of a number.
+<p>
+<ul>
+<li> Grouping ( ' <code>)</code> [TRIO]. The number is separated by the locale thousand separator. <div class="fragment"><pre>
+ trio_printf("|%'ld|\n", 1234567);
+ |1,234,567|
+</pre></div></ul>
+<em>Floating-point</em> ( <code>e</code>, <code>E)</code>
+<p>
+Output a decimal floating-point number. The style is <code>[-]9.99e[-]9</code>, where <ul>
+<li> <code>[-]9.99</code> is the mantissa (as described for the <code>f</code>, <code>F</code> specifier), and <li> <code>e[-]9</code> is the exponent indicator (either <code>e</code> or <code>E</code>, depending on the floating-point specifier), followed by an optional sign and the exponent</ul>
+If the precision is wider than the maximum number of digits that can be represented by the floating-point unit, then the number will be adequately rounded. For example, assuming DBL_DIG is 15 <div class="fragment"><pre>
+ trio_printf("|%.18e|\n", (1.0 / 3.0));
+ |3.333333333333333000e-01|
+</pre></div>
+<p>
+<em>Floating-point</em> ( <code>f</code>, <code>F</code> )
+<p>
+Output a decimal floating-point number. The style is <code>[-]9.99</code>, where <ul>
+<li> <code>[-]</code> is an optional sign (either <code>+</code> or <code>-)</code>, <li> <code>9</code> is the integer-part (possibly interspersed with thousand-separators), <li> . <code>is</code> the decimal-point (depending on the locale), and <li> <code>99</code> is the fractional-part.</ul>
+If more digits are needed to output the number, than can be represented with the accuracy of the floating-point unit, then the number will be adequately rounded. For example, assuming that DBL_DIG is 15 <div class="fragment"><pre>
+ trio_printf("|%f|\n", (2.0 / 3.0) * 1E18);
+ |666666666666666700.000000|
+</pre></div>
+<p>
+The following modifiers holds a special meaning for this specifier <ul>
+<li> Alternative ( <code>#</code> ) [C99]. Add decimal point. <li> Grouping ( ' <code>)</code> [TRIO]. Group integer part of number into thousands (according to locale).</ul>
+<em>Floating-point</em> ( <code>g</code>, <code>G)</code>
+<p>
+Output a decimal floating-point representation of a number. The format of either the <code>f</code>, <code>F</code> specifier or the <code>e</code>, <code>E</code> specifier is used, whatever produces the shortest result.
+<p>
+<em>Integer</em> ( <code>i</code> )
+<p>
+Output a signed integer. Default base is 10.
+<p>
+<em>Errno</em> ( <code>m</code> ) [GNU]
+<p>
+<em>Count</em> ( <code>n</code> )
+<p>
+Insert into the location pointed to by the argument, the number of octets written to the output so far.
+<p>
+<em>Octal</em> ( <code>o</code> )
+<p>
+Output an octal (base 8) representation of a number.
+<p>
+<em>Pointer</em> ( <code>p</code> )
+<p>
+Ouput the address of the argument. The address is printed as a hexadecimal number. If the argument is the NULL pointer the text <code>(nil)</code> will be used instead. <ul>
+<li> Alternative ( <code>#</code> ) [TRIO]. Prepend 0x</ul>
+<em>String</em> ( <code>s</code>, <code>S</code> )
+<p>
+Output a string. The argument must point to a zero terminated string. If the argument is the NULL pointer the text <code>(nil)</code> will be used instead. <code>S</code> is equivalent to <code>ls</code>. <ul>
+<li> Alternative ( <code>#</code> ) [TRIO]. Escape non-printable characters.</ul>
+Non-printable characters are converted into C escapes, or hexadecimal numbers where no C escapes exists for the character. The C escapes, the hexadecimal number, and all backslashes are prepended by a backslash ( <code>\</code> ). The supported C escapes are <ul>
+<li> <code>\a</code> (\007) = alert <li> <code>\b</code> (\010) = backspace <li> <code>\f</code> (\014) = formfeed <li> <code>\n</code> (\012) = newline <li> <code>\r</code> (\015) = carriage return <li> <code>\t</code> (\011) = horizontal tab <li> <code>\v</code> (\013) = vertical tab</ul>
+<div class="fragment"><pre>
+ trio_printf("|One %s Three|One %'s Three|\n", "Two", "Two");
+ |One Two Three|One "Two" Three|
+
+ trio_printf("|Argument missing %s|\n", NULL);
+ |Argument missing (nil)|
+
+ trio_printf("|%#s|\n", "\007 \a.");
+ |\a \a.|
+</pre></div>
+<p>
+<em>Unsigned</em> ( <code>u</code> )
+<p>
+Output an unsigned integer. Default base is 10.
+<p>
+<em>Hex</em> ( <code>x</code>, <code>X</code> )
+<p>
+Output a hexadecimal (base 16) representation of a number.
+<p>
+<ul>
+<li> Alternative ( <code>#</code> ). Preceed the number by <code>0x</code> ( or <code>0X</code> ). The two characters are counted as part of the width.</ul>
+<em>User-defined</em> ( <code>&lt;&gt;</code> )
+<p>
+Invoke user-defined formatting. See <a class="el" href="group___user_defined.html#a0">trio_register</a> for further information.
+<p>
+<b>RETURN</b> <b>VALUES</b>
+<p>
+All functions returns the number of outputted characters. If an error occured then a negative error code is returned [TRIO]. Note that this is a deviation from the standard, which simply returns -1 (or EOF) and errno set appropriately. The error condition can be detected by checking whether the function returns a negative number or not, and the number can be parsed with the following macros. The error codes are primarily intended as debugging aide for the developer.
+<p>
+<ul>
+<li> TRIO_EINVAL: Invalid argument. <li> TRIO_ETOOMANY: Too many arguments. <li> TRIO_EDBLREF: Double argument reference. <li> TRIO_EGAP: Argument reference gap. <li> TRIO_ENOMEM: Out of memory. <li> TRIO_ERANGE: Invalid range. <li> TRIO_ERRNO: The error is specified by the errno variable.</ul>
+Example: <div class="fragment"><pre>
+ int rc;
+
+ rc = trio_printf("%r\n", 42);
+ if (rc &lt; 0) {
+ if (TRIO_ERROR_CODE(rc) != TRIO_EOF) {
+ trio_printf("Error: %s at position %d\n",
+ TRIO_ERROR_NAME(rc),
+ TRIO_ERROR_POSITION(rc));
+ }
+ }
+</pre></div>
+<p>
+<b>SEE</b> <b>ALSO</b>
+<p>
+<em>trio_scanf</em>, <em>trio_register</em>.
+<p>
+<b>NOTES</b>
+<p>
+The printfv family uses an array rather than the stack to pass arguments. This means that <code>short</code> <code>int</code> and <code>float</code> values will not be handled by the default argument promotion in C. Instead, these values must be explicitly converted with the Short (h) modifier in both cases.
+<p>
+Example: <div class="fragment"><pre>
+ void *array[2];
+ float float_number = 42.0;
+ short short_number = 42;
+
+ array[0] = &amp;float_number;
+ array[1] = &amp;short_number;
+
+ trio_printfv("%hf %hd\n", array); /* CORRECT */
+ trio_printfv("%f %d\n", array); /* WRONG */
+</pre></div>
+<p>
+<b>CONFORMING</b> <b>TO</b>
+<p>
+Throughout this document the following abbreviations have been used to indicate what standard a feature conforms to. If nothing else is indicated ANSI C (C89) is assumed.
+<p>
+<ul>
+<li> [C89] ANSI X3.159-1989 <li> [C99] ISO/IEC 9899:1999 <li> [UNIX98] The Single UNIX Specification, Version 2 <li> [BSD] 4.4BSD <li> [GNU] GNU libc <li> [MSVC] Microsoft Visual C <li> [MISC] Other non-standard sources <li> [TRIO] Extensions specific for this package </ul>
+<hr><h2>Function Documentation</h2>
+<a name="a6" doxytag="trio.c::trio_dprintf"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> int trio_dprintf </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">int&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>fd</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>...&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Print to file descriptor.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>fd</em>&nbsp;</td><td>
+File descriptor. </td></tr>
+<tr><td valign=top><em>format</em>&nbsp;</td><td>
+Formatting string. </td></tr>
+<tr><td valign=top><em>...</em>&nbsp;</td><td>
+Arguments. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Number of printed characters. </dl> </td>
+ </tr>
+</table>
+<a name="a8" doxytag="trio.c::trio_dprintfv"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> int trio_dprintfv </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">int&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>fd</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>trio_pointer_t *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Print to file descriptor.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>fd</em>&nbsp;</td><td>
+File descriptor. </td></tr>
+<tr><td valign=top><em>format</em>&nbsp;</td><td>
+Formatting string. </td></tr>
+<tr><td valign=top><em>args</em>&nbsp;</td><td>
+Arguments. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Number of printed characters. </dl> </td>
+ </tr>
+</table>
+<a name="a3" doxytag="trio.c::trio_fprintf"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> int trio_fprintf </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">FILE *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>file</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>...&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Print to file.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>file</em>&nbsp;</td><td>
+File pointer. </td></tr>
+<tr><td valign=top><em>format</em>&nbsp;</td><td>
+Formatting string. </td></tr>
+<tr><td valign=top><em>...</em>&nbsp;</td><td>
+Arguments. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Number of printed characters. </dl> </td>
+ </tr>
+</table>
+<a name="a5" doxytag="trio.c::trio_fprintfv"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> int trio_fprintfv </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">FILE *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>file</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>trio_pointer_t *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Print to file.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>file</em>&nbsp;</td><td>
+File pointer. </td></tr>
+<tr><td valign=top><em>format</em>&nbsp;</td><td>
+Formatting string. </td></tr>
+<tr><td valign=top><em>args</em>&nbsp;</td><td>
+Arguments. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Number of printed characters. </dl> </td>
+ </tr>
+</table>
+<a name="a0" doxytag="trio.c::trio_printf"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> int trio_printf </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>...&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Print to standard output stream.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>format</em>&nbsp;</td><td>
+Formatting string. </td></tr>
+<tr><td valign=top><em>...</em>&nbsp;</td><td>
+Arguments. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Number of printed characters. </dl> </td>
+ </tr>
+</table>
+<a name="a2" doxytag="trio.c::trio_printfv"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> int trio_printfv </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>trio_pointer_t *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Print to standard output stream.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>format</em>&nbsp;</td><td>
+Formatting string. </td></tr>
+<tr><td valign=top><em>args</em>&nbsp;</td><td>
+Arguments. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Number of printed characters. </dl> </td>
+ </tr>
+</table>
+<a name="a15" doxytag="trio.c::trio_snprintf"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> int trio_snprintf </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>buffer</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>size_t&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>max</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>...&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Print at most <code>max</code> characters to string.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>buffer</em>&nbsp;</td><td>
+Output string. </td></tr>
+<tr><td valign=top><em>max</em>&nbsp;</td><td>
+Maximum number of characters to print. </td></tr>
+<tr><td valign=top><em>format</em>&nbsp;</td><td>
+Formatting string. </td></tr>
+<tr><td valign=top><em>...</em>&nbsp;</td><td>
+Arguments. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Number of printed characters. </dl> </td>
+ </tr>
+</table>
+<a name="a17" doxytag="trio.c::trio_snprintfv"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> int trio_snprintfv </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>buffer</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>size_t&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>max</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>trio_pointer_t *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Print at most <code>max</code> characters to string.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>buffer</em>&nbsp;</td><td>
+Output string. </td></tr>
+<tr><td valign=top><em>max</em>&nbsp;</td><td>
+Maximum number of characters to print. </td></tr>
+<tr><td valign=top><em>format</em>&nbsp;</td><td>
+Formatting string. </td></tr>
+<tr><td valign=top><em>args</em>&nbsp;</td><td>
+Arguments. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Number of printed characters. </dl> </td>
+ </tr>
+</table>
+<a name="a12" doxytag="trio.c::trio_sprintf"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> int trio_sprintf </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>buffer</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>...&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Print to string.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>buffer</em>&nbsp;</td><td>
+Output string. </td></tr>
+<tr><td valign=top><em>format</em>&nbsp;</td><td>
+Formatting string. </td></tr>
+<tr><td valign=top><em>...</em>&nbsp;</td><td>
+Arguments. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Number of printed characters. </dl> </td>
+ </tr>
+</table>
+<a name="a14" doxytag="trio.c::trio_sprintfv"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> int trio_sprintfv </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>buffer</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>trio_pointer_t *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Print to string.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>buffer</em>&nbsp;</td><td>
+Output string. </td></tr>
+<tr><td valign=top><em>format</em>&nbsp;</td><td>
+Formatting string. </td></tr>
+<tr><td valign=top><em>args</em>&nbsp;</td><td>
+Arguments. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Number of printed characters. </dl> </td>
+ </tr>
+</table>
+<a name="a7" doxytag="trio.c::trio_vdprintf"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> int trio_vdprintf </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">int&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>fd</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>va_list&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Print to file descriptor.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>fd</em>&nbsp;</td><td>
+File descriptor. </td></tr>
+<tr><td valign=top><em>format</em>&nbsp;</td><td>
+Formatting string. </td></tr>
+<tr><td valign=top><em>args</em>&nbsp;</td><td>
+Arguments. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Number of printed characters. </dl> </td>
+ </tr>
+</table>
+<a name="a4" doxytag="trio.c::trio_vfprintf"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> int trio_vfprintf </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">FILE *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>file</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>va_list&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Print to file.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>file</em>&nbsp;</td><td>
+File pointer. </td></tr>
+<tr><td valign=top><em>format</em>&nbsp;</td><td>
+Formatting string. </td></tr>
+<tr><td valign=top><em>args</em>&nbsp;</td><td>
+Arguments. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Number of printed characters. </dl> </td>
+ </tr>
+</table>
+<a name="a1" doxytag="trio.c::trio_vprintf"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> int trio_vprintf </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>va_list&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Print to standard output stream.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>format</em>&nbsp;</td><td>
+Formatting string. </td></tr>
+<tr><td valign=top><em>args</em>&nbsp;</td><td>
+Arguments. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Number of printed characters. </dl> </td>
+ </tr>
+</table>
+<a name="a16" doxytag="trio.c::trio_vsnprintf"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> int trio_vsnprintf </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>buffer</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>size_t&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>max</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>va_list&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Print at most <code>max</code> characters to string.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>buffer</em>&nbsp;</td><td>
+Output string. </td></tr>
+<tr><td valign=top><em>max</em>&nbsp;</td><td>
+Maximum number of characters to print. </td></tr>
+<tr><td valign=top><em>format</em>&nbsp;</td><td>
+Formatting string. </td></tr>
+<tr><td valign=top><em>args</em>&nbsp;</td><td>
+Arguments. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Number of printed characters. </dl> </td>
+ </tr>
+</table>
+<a name="a13" doxytag="trio.c::trio_vsprintf"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> int trio_vsprintf </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>buffer</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>va_list&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>args</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Print to string.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>buffer</em>&nbsp;</td><td>
+Output string. </td></tr>
+<tr><td valign=top><em>format</em>&nbsp;</td><td>
+Formatting string. </td></tr>
+<tr><td valign=top><em>args</em>&nbsp;</td><td>
+Arguments. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Number of printed characters. </dl> </td>
+ </tr>
+</table>
+<HR>
+<center class="copyright">Copyright (C) 2001 Bj&oslash;rn Reese and Daniel Stenberg.</center>
+</body>
+</html>
diff --git a/trio/html/group___scanf.html b/trio/html/group___scanf.html
new file mode 100644
index 00000000..0c8d9d2b
--- /dev/null
+++ b/trio/html/group___scanf.html
@@ -0,0 +1,145 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+ <title>TRIO</title>
+ <link href="trio.css" rel="stylesheet" type="text/css">
+</head>
+<body>
+<!-- Generated by Doxygen 1.2.12 -->
+<center>
+<a class="qindex" href="index.html">Main Page</a> &nbsp; <a class="qindex" href="modules.html">Modules</a> &nbsp; </center>
+<hr><h1>Formatted Scanning Functions.</h1>Variations of formatted scanning functions.
+<a href="#_details">More...</a><table border=0 cellpadding=0 cellspacing=0>
+<tr><td colspan=2><br><h2>Functions</h2></td></tr>
+<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___scanf.html#a0">trio_scanf</a> (const char *format,...)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Scan characters from standard input stream.</em> <a href="#a0">More...</a><em></em></font><br><br></td></tr>
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+Variations of formatted scanning functions.
+<p>
+<b>SYNOPSIS</b>
+<p>
+<div class="fragment"><pre>
+cc ... -ltrio -lm
+
+#include &lt;trio.h&gt;
+</pre></div>
+<p>
+<b>DESCRIPTION</b>
+<p>
+This documentation is incomplete. The documentation of the scanf family in [C99] and [UNIX98] also applies to the trio counterparts.
+<p>
+<b>SCANNING</b>
+<p>
+The scanning is controlled by the format string. The format string can contain normal text and conversion indicators. The normal text can be any character except the nil character (\000) and the percent character (\045 = '%'). Conversion indicators consists of an indication character (%), followed by zero or more conversion modifiers, and exactly one conversion specifier.
+<p>
+<b>Modifiers</b>
+<p>
+<em>Positional</em> ( <code>9$</code> ) [UNIX98]
+<p>
+See <a class="el" href="group___printf.html#a0">trio_printf</a>.
+<p>
+<b>Specifiers</b>
+<p>
+<em>Percent</em> ( <code>%</code> )
+<p>
+<em>Character</em> ( <code>c</code> )
+<p>
+<em>Decimal</em> ( <code>d</code> )
+<p>
+<em>Floating-point</em> ( <code>a</code>, <code>A</code>, <code>e</code>, <code>E</code>, <code>f</code>, <code>F</code>, <code>g</code>, <code>G</code> )
+<p>
+<em>Integer</em> ( <code>i</code> )
+<p>
+<em>Count</em> ( <code>n</code> )
+<p>
+<em>Octal</em> ( <code>o</code> )
+<p>
+<em>Pointer</em> ( <code>p</code> )
+<p>
+<em>String</em> ( <code>s</code> )
+<p>
+<em>Unsigned</em> ( <code>u</code> )
+<p>
+<em>Hex</em> ( <code>x</code>, <code>X</code> )
+<p>
+<em>Scanlist</em> ( <code>[]</code> )
+<p>
+Scanlist Exclusion (<code>^</code> )
+<p>
+Scanlist Range ( <code>-</code> ) [TRIO]
+<p>
+<ul>
+<li> Only increasing ranges, i.e. <code>[a-b]</code>, but not <code>[b-a]</code>. <li> Transitive ranges, ie. <code>[a-b-c]</code> equals <code>[a-c]</code>. <li> Trailing minus, ie. <code>[a-]</code> is interpreted as an <code>a</code> and a <code>-</code>. <li> Duplicates are ignored.</ul>
+Scanlist Equivalence Class Expression ( <code>[</code>= =<code>]</code> ) [TRIO]
+<p>
+Locale dependent (LC_COLLATE). Only one expression can appear inside the delimiters. <ul>
+<li> <code>[=a=]</code> All letters in the same equivalence class as the letter <code>a</code>. <div class="fragment"><pre>
+ trio_scanf("%[[=a=]b]\n", buffer);
+ trio_scanf("%[[=a=][=b=]]\n", buffer);
+</pre></div></ul>
+Scanlist Character Class Expression ( <code>[</code>: :<code>])</code> [TRIO] Locale dependent (LC_CTYPE). Only one expression can appear inside the delimiters. <ul>
+<li> <code>[:alnum:]</code> Same as <code>[:alpha:]</code> and <code>[:digit:]</code> <li> <code>[:alpha:]</code> Same as <code>[:lower:]</code> and <code>[:upper:]</code> <li> <code>[:cntrl:]</code> Control characters <li> <code>[:digit:]</code> Decimal digits <li> <code>[:graph:]</code> Printable characters except space <li> <code>[:lower:]</code> Lower case alphabetic letters <li> <code>[:print:]</code> Printable characters <li> <code>[:punct:]</code> Punctuation <li> <code>[:space:]</code> Whitespace characters <li> <code>[:upper:]</code> Upper case alphabetic letters <li> <code>[:xdigit:]</code> Hexadecimal digits <div class="fragment"><pre>
+ trio_scanf("%[[:alnum:]]\n", buffer);
+ trio_scanf("%[[:alpha:][:digit:]]\n", buffer);
+</pre></div></ul>
+<b>RETURN</b> <b>VALUES</b>
+<p>
+<b>SEE</b> <b>ALSO</b>
+<p>
+<a class="el" href="group___printf.html#a0">trio_printf</a> <hr><h2>Function Documentation</h2>
+<a name="a0" doxytag="trio.c::trio_scanf"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> int trio_scanf </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>...&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Scan characters from standard input stream.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>format</em>&nbsp;</td><td>
+Formatting string. </td></tr>
+<tr><td valign=top><em>...</em>&nbsp;</td><td>
+Arguments. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Number of scanned characters. </dl> </td>
+ </tr>
+</table>
+<HR>
+<center class="copyright">Copyright (C) 2001 Bj&oslash;rn Reese and Daniel Stenberg.</center>
+</body>
+</html>
diff --git a/trio/html/group___special_quantities.html b/trio/html/group___special_quantities.html
new file mode 100644
index 00000000..cdc294f2
--- /dev/null
+++ b/trio/html/group___special_quantities.html
@@ -0,0 +1,390 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+ <title>TRIO</title>
+ <link href="trio.css" rel="stylesheet" type="text/css">
+</head>
+<body>
+<!-- Generated by Doxygen 1.2.12 -->
+<center>
+<a class="qindex" href="index.html">Main Page</a> &nbsp; <a class="qindex" href="modules.html">Modules</a> &nbsp; </center>
+<hr><h1>Special Quantifies.</h1>Functions to detect and fabricate special quantities in floating-point numbers.
+<a href="#_details">More...</a><table border=0 cellpadding=0 cellspacing=0>
+<tr><td colspan=2><br><h2>Functions</h2></td></tr>
+<tr><td nowrap align=right valign=top>double&nbsp;</td><td valign=bottom><a class="el" href="group___special_quantities.html#a1">trio_nzero</a> (void)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Generate negative zero.</em> <a href="#a1">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>double&nbsp;</td><td valign=bottom><a class="el" href="group___special_quantities.html#a2">trio_pinf</a> (void)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Generate positive infinity.</em> <a href="#a2">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>double&nbsp;</td><td valign=bottom><a class="el" href="group___special_quantities.html#a3">trio_ninf</a> (void)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Generate negative infinity.</em> <a href="#a3">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>double&nbsp;</td><td valign=bottom><a class="el" href="group___special_quantities.html#a4">trio_nan</a> (void)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Generate NaN.</em> <a href="#a4">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___special_quantities.html#a5">trio_isnan</a> (double number)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Check for NaN.</em> <a href="#a5">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___special_quantities.html#a6">trio_isinf</a> (double number)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Check for infinity.</em> <a href="#a6">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___special_quantities.html#a7">trio_isfinite</a> (double number)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Check for finity.</em> <a href="#a7">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___special_quantities.html#a9">trio_signbit</a> (double number)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Examine the sign of a number.</em> <a href="#a9">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a class="el" href="group___special_quantities.html#a10">trio_fpclassify</a> (double number)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Examine the class of a number.</em> <a href="#a10">More...</a><em></em></font><br><br></td></tr>
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+Functions to detect and fabricate special quantities in floating-point numbers.
+<p>
+<b>SYNOPSIS</b>
+<p>
+<div class="fragment"><pre>
+cc ... -ltrio -lm
+
+#include &lt;trionan.h&gt;
+</pre></div>
+<p>
+<b>DESCRIPTION</b>
+<p>
+Certain arithmetical operations does not result in normal numbers. Instead they result in special quantities that must be handled differently by the floating-point hardware. These includes Infinity and Not-A-Number (NaN).
+<p>
+For example, 0/0 (zero divided by zero) yields NaN. Any operation which involves a NaN will result in NaN. Any comparison involving NaN will be unsuccessful, even if NaN is compared to NaN.
+<p>
+These special quantities are represented with special bit patterns by the floating-point hardware, and this bit patterns depend on the hardware. There may even be hardware that does not support special quantities, so the functions in this module are not guaranteed to work on all platforms.
+<p>
+The approach used in this module is to (in decreasing order of importance) <ul>
+<li> Use C99 functionality when available. <li> Use IEEE 754-1985 bit patterns if possible. <li> Use platform-specific techniques.</ul>
+<b>NOTES</b>
+<p>
+This module does not depend on the rest of trio, and can thus be reused separately. The following files are necessary: <ul>
+<li> <code>triodef.h</code> <li> <code>trionan.h</code> <li> <code>trionan.c</code> </ul>
+<hr><h2>Function Documentation</h2>
+<a name="a10" doxytag="trionan.c::trio_fpclassify"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> int trio_fpclassify </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">double&nbsp;</td>
+ <td class="mdname1" valign="top" nowrap>&nbsp; <em>number</em> </td>
+ <td class="md" valign="top">)&nbsp;</td>
+ <td class="md" nowrap></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Examine the class of a number.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>number</em>&nbsp;</td><td>
+An arbitrary floating-point number. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Enumerable value indicating the class of <code>number</code> </dl> </td>
+ </tr>
+</table>
+<a name="a7" doxytag="trionan.c::trio_isfinite"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> int trio_isfinite </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">double&nbsp;</td>
+ <td class="mdname1" valign="top" nowrap>&nbsp; <em>number</em> </td>
+ <td class="md" valign="top">)&nbsp;</td>
+ <td class="md" nowrap></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Check for finity.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>number</em>&nbsp;</td><td>
+An arbitrary floating-point number. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Boolean value indicating whether or not the number is a finite. </dl> </td>
+ </tr>
+</table>
+<a name="a6" doxytag="trionan.c::trio_isinf"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> int trio_isinf </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">double&nbsp;</td>
+ <td class="mdname1" valign="top" nowrap>&nbsp; <em>number</em> </td>
+ <td class="md" valign="top">)&nbsp;</td>
+ <td class="md" nowrap></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Check for infinity.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>number</em>&nbsp;</td><td>
+An arbitrary floating-point number. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+1 if positive infinity, -1 if negative infinity, 0 otherwise. </dl> </td>
+ </tr>
+</table>
+<a name="a5" doxytag="trionan.c::trio_isnan"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> int trio_isnan </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">double&nbsp;</td>
+ <td class="mdname1" valign="top" nowrap>&nbsp; <em>number</em> </td>
+ <td class="md" valign="top">)&nbsp;</td>
+ <td class="md" nowrap></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Check for NaN.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>number</em>&nbsp;</td><td>
+An arbitrary floating-point number. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Boolean value indicating whether or not the number is a NaN. </dl> </td>
+ </tr>
+</table>
+<a name="a4" doxytag="trionan.c::trio_nan"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> double trio_nan </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">void&nbsp;</td>
+ <td class="mdname1" valign="top" nowrap>&nbsp; </td>
+ <td class="md" valign="top">)&nbsp;</td>
+ <td class="md" nowrap></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Generate NaN.
+<p>
+<dl compact><dt><b>
+Returns: </b><dd>
+Floating-point representation of NaN. </dl> </td>
+ </tr>
+</table>
+<a name="a3" doxytag="trionan.c::trio_ninf"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> double trio_ninf </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">void&nbsp;</td>
+ <td class="mdname1" valign="top" nowrap>&nbsp; </td>
+ <td class="md" valign="top">)&nbsp;</td>
+ <td class="md" nowrap></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Generate negative infinity.
+<p>
+<dl compact><dt><b>
+Returns: </b><dd>
+Floating-point value of negative infinity. </dl> </td>
+ </tr>
+</table>
+<a name="a1" doxytag="trionan.c::trio_nzero"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> double trio_nzero </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">void&nbsp;</td>
+ <td class="mdname1" valign="top" nowrap>&nbsp; </td>
+ <td class="md" valign="top">)&nbsp;</td>
+ <td class="md" nowrap></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Generate negative zero.
+<p>
+<dl compact><dt><b>
+Returns: </b><dd>
+Floating-point representation of negative zero. </dl> </td>
+ </tr>
+</table>
+<a name="a2" doxytag="trionan.c::trio_pinf"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> double trio_pinf </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">void&nbsp;</td>
+ <td class="mdname1" valign="top" nowrap>&nbsp; </td>
+ <td class="md" valign="top">)&nbsp;</td>
+ <td class="md" nowrap></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Generate positive infinity.
+<p>
+<dl compact><dt><b>
+Returns: </b><dd>
+Floating-point representation of positive infinity. </dl> </td>
+ </tr>
+</table>
+<a name="a9" doxytag="trionan.c::trio_signbit"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> int trio_signbit </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">double&nbsp;</td>
+ <td class="mdname1" valign="top" nowrap>&nbsp; <em>number</em> </td>
+ <td class="md" valign="top">)&nbsp;</td>
+ <td class="md" nowrap></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Examine the sign of a number.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>number</em>&nbsp;</td><td>
+An arbitrary floating-point number. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Boolean value indicating whether or not the number has the sign bit set (i.e. is negative). </dl> </td>
+ </tr>
+</table>
+<HR>
+<center class="copyright">Copyright (C) 2001 Bj&oslash;rn Reese and Daniel Stenberg.</center>
+</body>
+</html>
diff --git a/trio/html/group___static_strings.html b/trio/html/group___static_strings.html
new file mode 100644
index 00000000..840f36a5
--- /dev/null
+++ b/trio/html/group___static_strings.html
@@ -0,0 +1,1809 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+ <title>TRIO</title>
+ <link href="trio.css" rel="stylesheet" type="text/css">
+</head>
+<body>
+<!-- Generated by Doxygen 1.2.12 -->
+<center>
+<a class="qindex" href="index.html">Main Page</a> &nbsp; <a class="qindex" href="modules.html">Modules</a> &nbsp; </center>
+<hr><h1>Static String Functions.</h1>Replacements for the standard C string functions.
+<a href="#_details">More...</a><table border=0 cellpadding=0 cellspacing=0>
+<tr><td colspan=2><br><h2>Functions</h2></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC char *&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a0">trio_create</a> (size_t size)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Create new string.</em> <a href="#a0">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC void&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a1">trio_destroy</a> (char *string)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Destroy string.</em> <a href="#a1">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC size_t&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a2">trio_length</a> (const char *string)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Count the number of characters in a string.</em> <a href="#a2">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a3">trio_append</a> (char *target, const char *source)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Append <code>source</code> at the end of <code>target</code>.</em> <a href="#a3">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a4">trio_append_max</a> (char *target, size_t max, const char *source)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Append at most <code>max</code> characters from <code>source</code> to <code>target</code>.</em> <a href="#a4">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a5">trio_contains</a> (const char *string, const char *substring)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Determine if a string contains a substring.</em> <a href="#a5">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a6">trio_copy</a> (char *target, const char *source)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Copy <code>source</code> to <code>target</code>.</em> <a href="#a6">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a7">trio_copy_max</a> (char *target, size_t max, const char *source)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Copy at most <code>max</code> characters from <code>source</code> to <code>target</code>.</em> <a href="#a7">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC char *&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a9">trio_duplicate</a> (const char *source)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Duplicate <code>source</code>.</em> <a href="#a9">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC char *&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a10">trio_duplicate_max</a> (const char *source, size_t max)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Duplicate at most <code>max</code> characters of <code>source</code>.</em> <a href="#a10">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a11">trio_equal</a> (const char *first, const char *second)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Compare if two strings are equal.</em> <a href="#a11">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a12">trio_equal_case</a> (const char *first, const char *second)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Compare if two strings are equal.</em> <a href="#a12">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a13">trio_equal_case_max</a> (const char *first, size_t max, const char *second)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Compare if two strings up until the first <code>max</code> characters are equal.</em> <a href="#a13">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a14">trio_equal_locale</a> (const char *first, const char *second)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Compare if two strings are equal.</em> <a href="#a14">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a15">trio_equal_max</a> (const char *first, size_t max, const char *second)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Compare if two strings up until the first <code>max</code> characters are equal.</em> <a href="#a15">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC const char *&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a16">trio_error</a> (int error_number)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Provide a textual description of an error code (errno).</em> <a href="#a16">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC size_t&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a17">trio_format_date_max</a> (char *target, size_t max, const char *format, const struct tm *datetime)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Format the date/time according to <code>format</code>.</em> <a href="#a17">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC unsigned <br>
+long&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a18">trio_hash</a> (const char *string, int type)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Calculate a hash value for a string.</em> <a href="#a18">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC char *&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a19">trio_index</a> (const char *string, int character)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Find first occurrence of a character in a string.</em> <a href="#a19">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC char *&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a20">trio_index_last</a> (const char *string, int character)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Find last occurrence of a character in a string.</em> <a href="#a20">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a21">trio_lower</a> (char *target)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Convert the alphabetic letters in the string to lower-case.</em> <a href="#a21">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a22">trio_match</a> (const char *string, const char *pattern)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Compare two strings using wildcards.</em> <a href="#a22">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a23">trio_match_case</a> (const char *string, const char *pattern)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Compare two strings using wildcards.</em> <a href="#a23">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC size_t&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a24">trio_span_function</a> (char *target, const char *source, int(*Function)(int))</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Execute a function on each character in string.</em> <a href="#a24">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC char *&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a25">trio_substring</a> (const char *string, const char *substring)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Search for a substring in a string.</em> <a href="#a25">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC char *&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a26">trio_substring_max</a> (const char *string, size_t max, const char *substring)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Search for a substring in the first <code>max</code> characters of a string.</em> <a href="#a26">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC char *&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a27">trio_tokenize</a> (char *string, const char *delimiters)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Tokenize string.</em> <a href="#a27">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC trio_long_double_t&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a28">trio_to_long_double</a> (const char *source, char **endp)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Convert string to floating-point number.</em> <a href="#a28">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC double&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a29">trio_to_double</a> (const char *source, char **endp)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Convert string to floating-point number.</em> <a href="#a29">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC float&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a30">trio_to_float</a> (const char *source, char **endp)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Convert string to floating-point number.</em> <a href="#a30">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC long&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a31">trio_to_long</a> (const char *string, char **endp, int base)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Convert string to signed integer.</em> <a href="#a31">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC unsigned <br>
+long&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a32">trio_to_unsigned_long</a> (const char *string, char **endp, int base)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Convert string to unsigned integer.</em> <a href="#a32">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>TRIO_STRING_PUBLIC int&nbsp;</td><td valign=bottom><a class="el" href="group___static_strings.html#a33">trio_upper</a> (char *target)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Convert the alphabetic letters in the string to upper-case.</em> <a href="#a33">More...</a><em></em></font><br><br></td></tr>
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+Replacements for the standard C string functions.
+<p>
+<b>SYNOPSIS</b>
+<p>
+<div class="fragment"><pre>
+cc ... -ltrio -lm
+
+#include &lt;triostr.h&gt;
+</pre></div>
+<p>
+<b>DESCRIPTION</b>
+<p>
+This package renames, fixes, and extends the standard C string handling functions.
+<p>
+<b>Naming</b>
+<p>
+Renaming is done to provide more clear names, to provide a consistant naming and argument policy, and to hide portability issues.
+<p>
+<ul>
+<li> All functions starts with "trio_". <li> Target is always the first argument, if present, except where the target is optional, such as <a class="el" href="group___static_strings.html#a29">trio_to_double</a>. <li> Functions requiring a size for target includes "_max" in its name, and the size is always the second argument. <li> Functions performing case-sensitive operations includes "_case" in its name.</ul>
+<b>Fixing</b>
+<p>
+Fixing is done to avoid subtle error conditions. For example, <code>strncpy</code> does not terminate the result with a zero if the source string is bigger than the maximal length, so technically the result is not a C string anymore. <a class="el" href="group___static_strings.html#a7">trio_copy_max</a> makes sure that the result is zero terminated.
+<p>
+<b>Extending</b>
+<p>
+Extending is done to provide a richer set of fundamental functions. This includes functionality such as wildcard matching ( <code>trio_match</code> ) and calculation of hash values ( <code>trio_hash</code> ). <hr><h2>Function Documentation</h2>
+<a name="a3" doxytag="triostr.c::trio_append"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC int trio_append </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>target</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>source</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Append <code>source</code> at the end of <code>target</code>.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>target</em>&nbsp;</td><td>
+Target string. </td></tr>
+<tr><td valign=top><em>source</em>&nbsp;</td><td>
+Source string. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Boolean value indicating success or failure.</dl><dl compact><dt><b>
+Precondition: </b><dd>
+<code>target</code> must point to a memory chunk with sufficient room to contain the <code>target</code> string and <code>source</code> string. <dd>
+No boundary checking is performed, so insufficient memory will result in a buffer overrun. </dl><dl compact><dt><b>
+Postcondition: </b><dd>
+<code>target</code> will be zero terminated. </dl> </td>
+ </tr>
+</table>
+<a name="a4" doxytag="triostr.c::trio_append_max"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC int trio_append_max </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>target</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>size_t&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>max</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>source</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Append at most <code>max</code> characters from <code>source</code> to <code>target</code>.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>target</em>&nbsp;</td><td>
+Target string. </td></tr>
+<tr><td valign=top><em>max</em>&nbsp;</td><td>
+Maximum number of characters to append. </td></tr>
+<tr><td valign=top><em>source</em>&nbsp;</td><td>
+Source string. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Boolean value indicating success or failure.</dl><dl compact><dt><b>
+Precondition: </b><dd>
+<code>target</code> must point to a memory chuck with sufficient room to contain the <code>target</code> string and the <code>source</code> string (at most <code>max</code> characters). <dd>
+No boundary checking is performed, so insufficient memory will result in a buffer overrun. </dl><dl compact><dt><b>
+Postcondition: </b><dd>
+<code>target</code> will be zero terminated. </dl> </td>
+ </tr>
+</table>
+<a name="a5" doxytag="triostr.c::trio_contains"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC int trio_contains </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>string</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>substring</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Determine if a string contains a substring.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>string</em>&nbsp;</td><td>
+String to be searched. </td></tr>
+<tr><td valign=top><em>substring</em>&nbsp;</td><td>
+String to be found. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Boolean value indicating success or failure. </dl> </td>
+ </tr>
+</table>
+<a name="a6" doxytag="triostr.c::trio_copy"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC int trio_copy </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>target</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>source</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Copy <code>source</code> to <code>target</code>.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>target</em>&nbsp;</td><td>
+Target string. </td></tr>
+<tr><td valign=top><em>source</em>&nbsp;</td><td>
+Source string. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Boolean value indicating success or failure.</dl><dl compact><dt><b>
+Precondition: </b><dd>
+<code>target</code> must point to a memory chunk with sufficient room to contain the <code>source</code> string. <dd>
+No boundary checking is performed, so insufficient memory will result in a buffer overrun. </dl><dl compact><dt><b>
+Postcondition: </b><dd>
+<code>target</code> will be zero terminated. </dl> </td>
+ </tr>
+</table>
+<a name="a7" doxytag="triostr.c::trio_copy_max"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC int trio_copy_max </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>target</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>size_t&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>max</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>source</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Copy at most <code>max</code> characters from <code>source</code> to <code>target</code>.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>target</em>&nbsp;</td><td>
+Target string. </td></tr>
+<tr><td valign=top><em>max</em>&nbsp;</td><td>
+Maximum number of characters to append. </td></tr>
+<tr><td valign=top><em>source</em>&nbsp;</td><td>
+Source string. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Boolean value indicating success or failure.</dl><dl compact><dt><b>
+Precondition: </b><dd>
+<code>target</code> must point to a memory chunk with sufficient room to contain the <code>source</code> string (at most <code>max</code> characters). <dd>
+No boundary checking is performed, so insufficient memory will result in a buffer overrun. </dl><dl compact><dt><b>
+Postcondition: </b><dd>
+<code>target</code> will be zero terminated. </dl> </td>
+ </tr>
+</table>
+<a name="a0" doxytag="triostr.c::trio_create"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC char* trio_create </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">size_t&nbsp;</td>
+ <td class="mdname1" valign="top" nowrap>&nbsp; <em>size</em> </td>
+ <td class="md" valign="top">)&nbsp;</td>
+ <td class="md" nowrap></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Create new string.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>size</em>&nbsp;</td><td>
+Size of new string. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Pointer to string, or NULL if allocation failed. </dl> </td>
+ </tr>
+</table>
+<a name="a1" doxytag="triostr.c::trio_destroy"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC void trio_destroy </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">char *&nbsp;</td>
+ <td class="mdname1" valign="top" nowrap>&nbsp; <em>string</em> </td>
+ <td class="md" valign="top">)&nbsp;</td>
+ <td class="md" nowrap></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Destroy string.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>string</em>&nbsp;</td><td>
+String to be freed. </td></tr>
+</table>
+</dl> </td>
+ </tr>
+</table>
+<a name="a9" doxytag="triostr.c::trio_duplicate"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC char* trio_duplicate </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">const char *&nbsp;</td>
+ <td class="mdname1" valign="top" nowrap>&nbsp; <em>source</em> </td>
+ <td class="md" valign="top">)&nbsp;</td>
+ <td class="md" nowrap></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Duplicate <code>source</code>.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>source</em>&nbsp;</td><td>
+Source string. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+A copy of the <code>source</code> string.</dl><dl compact><dt><b>
+Postcondition: </b><dd>
+<code>target</code> will be zero terminated. </dl> </td>
+ </tr>
+</table>
+<a name="a10" doxytag="triostr.c::trio_duplicate_max"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC char* trio_duplicate_max </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>source</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>size_t&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>max</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Duplicate at most <code>max</code> characters of <code>source</code>.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>source</em>&nbsp;</td><td>
+Source string. </td></tr>
+<tr><td valign=top><em>max</em>&nbsp;</td><td>
+Maximum number of characters to duplicate. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+A copy of the <code>source</code> string.</dl><dl compact><dt><b>
+Postcondition: </b><dd>
+<code>target</code> will be zero terminated. </dl> </td>
+ </tr>
+</table>
+<a name="a11" doxytag="triostr.c::trio_equal"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC int trio_equal </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>first</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>second</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Compare if two strings are equal.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>first</em>&nbsp;</td><td>
+First string. </td></tr>
+<tr><td valign=top><em>second</em>&nbsp;</td><td>
+Second string. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Boolean indicating whether the two strings are equal or not.</dl>Case-insensitive comparison. </td>
+ </tr>
+</table>
+<a name="a12" doxytag="triostr.c::trio_equal_case"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC int trio_equal_case </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>first</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>second</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Compare if two strings are equal.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>first</em>&nbsp;</td><td>
+First string. </td></tr>
+<tr><td valign=top><em>second</em>&nbsp;</td><td>
+Second string. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Boolean indicating whether the two strings are equal or not.</dl>Case-sensitive comparison. </td>
+ </tr>
+</table>
+<a name="a13" doxytag="triostr.c::trio_equal_case_max"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC int trio_equal_case_max </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>first</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>size_t&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>max</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>second</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Compare if two strings up until the first <code>max</code> characters are equal.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>first</em>&nbsp;</td><td>
+First string. </td></tr>
+<tr><td valign=top><em>max</em>&nbsp;</td><td>
+Maximum number of characters to compare. </td></tr>
+<tr><td valign=top><em>second</em>&nbsp;</td><td>
+Second string. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Boolean indicating whether the two strings are equal or not.</dl>Case-sensitive comparison. </td>
+ </tr>
+</table>
+<a name="a14" doxytag="triostr.c::trio_equal_locale"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC int trio_equal_locale </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>first</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>second</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Compare if two strings are equal.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>first</em>&nbsp;</td><td>
+First string. </td></tr>
+<tr><td valign=top><em>second</em>&nbsp;</td><td>
+Second string. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Boolean indicating whether the two strings are equal or not.</dl>Collating characters are considered equal. </td>
+ </tr>
+</table>
+<a name="a15" doxytag="triostr.c::trio_equal_max"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC int trio_equal_max </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>first</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>size_t&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>max</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>second</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Compare if two strings up until the first <code>max</code> characters are equal.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>first</em>&nbsp;</td><td>
+First string. </td></tr>
+<tr><td valign=top><em>max</em>&nbsp;</td><td>
+Maximum number of characters to compare. </td></tr>
+<tr><td valign=top><em>second</em>&nbsp;</td><td>
+Second string. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Boolean indicating whether the two strings are equal or not.</dl>Case-insensitive comparison. </td>
+ </tr>
+</table>
+<a name="a16" doxytag="triostr.c::trio_error"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC const char* trio_error </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">int&nbsp;</td>
+ <td class="mdname1" valign="top" nowrap>&nbsp; <em>error_number</em> </td>
+ <td class="md" valign="top">)&nbsp;</td>
+ <td class="md" nowrap></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Provide a textual description of an error code (errno).
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>error_number</em>&nbsp;</td><td>
+Error number. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Textual description of <code>error_number</code>. </dl> </td>
+ </tr>
+</table>
+<a name="a17" doxytag="triostr.c::trio_format_date_max"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC size_t trio_format_date_max </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>target</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>size_t&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>max</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>format</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const struct tm *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>datetime</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Format the date/time according to <code>format</code>.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>target</em>&nbsp;</td><td>
+Target string. </td></tr>
+<tr><td valign=top><em>max</em>&nbsp;</td><td>
+Maximum number of characters to format. </td></tr>
+<tr><td valign=top><em>format</em>&nbsp;</td><td>
+Formatting string. </td></tr>
+<tr><td valign=top><em>datetime</em>&nbsp;</td><td>
+Date/time structure. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Number of formatted characters.</dl>The formatting string accepts the same specifiers as the standard C function strftime. </td>
+ </tr>
+</table>
+<a name="a18" doxytag="triostr.c::trio_hash"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC unsigned long trio_hash </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>string</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>int&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>type</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Calculate a hash value for a string.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>string</em>&nbsp;</td><td>
+String to be calculated on. </td></tr>
+<tr><td valign=top><em>type</em>&nbsp;</td><td>
+Hash function. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Calculated hash value.</dl><code>type</code> can be one of the following <ul>
+<li> <code>TRIO_HASH_PLAIN</code> Plain hash function. </ul>
+ </td>
+ </tr>
+</table>
+<a name="a19" doxytag="triostr.c::trio_index"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC char* trio_index </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>string</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>int&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>character</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Find first occurrence of a character in a string.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>string</em>&nbsp;</td><td>
+String to be searched. </td></tr>
+<tr><td valign=top><em>character</em>&nbsp;</td><td>
+Character to be found. </td></tr>
+<tr><td valign=top><em>A</em>&nbsp;</td><td>
+pointer to the found character, or NULL if character was not found. </td></tr>
+</table>
+</dl> </td>
+ </tr>
+</table>
+<a name="a20" doxytag="triostr.c::trio_index_last"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC char* trio_index_last </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>string</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>int&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>character</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Find last occurrence of a character in a string.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>string</em>&nbsp;</td><td>
+String to be searched. </td></tr>
+<tr><td valign=top><em>character</em>&nbsp;</td><td>
+Character to be found. </td></tr>
+<tr><td valign=top><em>A</em>&nbsp;</td><td>
+pointer to the found character, or NULL if character was not found. </td></tr>
+</table>
+</dl> </td>
+ </tr>
+</table>
+<a name="a2" doxytag="triostr.c::trio_length"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC size_t trio_length </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">const char *&nbsp;</td>
+ <td class="mdname1" valign="top" nowrap>&nbsp; <em>string</em> </td>
+ <td class="md" valign="top">)&nbsp;</td>
+ <td class="md" nowrap></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Count the number of characters in a string.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>string</em>&nbsp;</td><td>
+String to measure. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Number of characters in @string. </dl> </td>
+ </tr>
+</table>
+<a name="a21" doxytag="triostr.c::trio_lower"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC int trio_lower </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">char *&nbsp;</td>
+ <td class="mdname1" valign="top" nowrap>&nbsp; <em>target</em> </td>
+ <td class="md" valign="top">)&nbsp;</td>
+ <td class="md" nowrap></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Convert the alphabetic letters in the string to lower-case.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>target</em>&nbsp;</td><td>
+String to be converted. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Number of processed characters (converted or not). </dl> </td>
+ </tr>
+</table>
+<a name="a22" doxytag="triostr.c::trio_match"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC int trio_match </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>string</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>pattern</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Compare two strings using wildcards.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>string</em>&nbsp;</td><td>
+String to be searched. </td></tr>
+<tr><td valign=top><em>pattern</em>&nbsp;</td><td>
+Pattern, including wildcards, to search for. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Boolean value indicating success or failure.</dl>Case-insensitive comparison.
+<p>
+The following wildcards can be used <ul>
+<li> <code>*</code> Match any number of characters. <li> ? <code>Match</code> a single character. </ul>
+ </td>
+ </tr>
+</table>
+<a name="a23" doxytag="triostr.c::trio_match_case"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC int trio_match_case </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>string</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>pattern</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Compare two strings using wildcards.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>string</em>&nbsp;</td><td>
+String to be searched. </td></tr>
+<tr><td valign=top><em>pattern</em>&nbsp;</td><td>
+Pattern, including wildcards, to search for. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Boolean value indicating success or failure.</dl>Case-sensitive comparison.
+<p>
+The following wildcards can be used <ul>
+<li> <code>*</code> Match any number of characters. <li> ? <code>Match</code> a single character. </ul>
+ </td>
+ </tr>
+</table>
+<a name="a24" doxytag="triostr.c::trio_span_function"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC size_t trio_span_function </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>target</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>source</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>int(*&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>Function</em>)(int)</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Execute a function on each character in string.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>target</em>&nbsp;</td><td>
+Target string. </td></tr>
+<tr><td valign=top><em>source</em>&nbsp;</td><td>
+Source string. </td></tr>
+<tr><td valign=top><em>Function</em>&nbsp;</td><td>
+Function to be executed. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Number of processed characters. </dl> </td>
+ </tr>
+</table>
+<a name="a25" doxytag="triostr.c::trio_substring"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC char* trio_substring </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>string</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>substring</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Search for a substring in a string.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>string</em>&nbsp;</td><td>
+String to be searched. </td></tr>
+<tr><td valign=top><em>substring</em>&nbsp;</td><td>
+String to be found. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Pointer to first occurrence of <code>substring</code> in <code>string</code>, or NULL if no match was found. </dl> </td>
+ </tr>
+</table>
+<a name="a26" doxytag="triostr.c::trio_substring_max"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC char* trio_substring_max </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>string</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>size_t&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>max</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>substring</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Search for a substring in the first <code>max</code> characters of a string.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>string</em>&nbsp;</td><td>
+String to be searched. </td></tr>
+<tr><td valign=top><em>max</em>&nbsp;</td><td>
+Maximum characters to be searched. </td></tr>
+<tr><td valign=top><em>substring</em>&nbsp;</td><td>
+String to be found. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Pointer to first occurrence of <code>substring</code> in <code>string</code>, or NULL if no match was found. </dl> </td>
+ </tr>
+</table>
+<a name="a29" doxytag="triostr.c::trio_to_double"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC double trio_to_double </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>source</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>char **&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>endp</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Convert string to floating-point number.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>source</em>&nbsp;</td><td>
+String to be converted. </td></tr>
+<tr><td valign=top><em>endp</em>&nbsp;</td><td>
+Pointer to end of the converted string. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+A floating-point number.</dl>See <a class="el" href="group___static_strings.html#a28">trio_to_long_double</a>. </td>
+ </tr>
+</table>
+<a name="a30" doxytag="triostr.c::trio_to_float"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC float trio_to_float </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>source</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>char **&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>endp</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Convert string to floating-point number.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>source</em>&nbsp;</td><td>
+String to be converted. </td></tr>
+<tr><td valign=top><em>endp</em>&nbsp;</td><td>
+Pointer to end of the converted string. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+A floating-point number.</dl>See <a class="el" href="group___static_strings.html#a28">trio_to_long_double</a>. </td>
+ </tr>
+</table>
+<a name="a31" doxytag="triostr.c::trio_to_long"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC long trio_to_long </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>string</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>char **&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>endp</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>int&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>base</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Convert string to signed integer.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>string</em>&nbsp;</td><td>
+String to be converted. </td></tr>
+<tr><td valign=top><em>endp</em>&nbsp;</td><td>
+Pointer to end of converted string. </td></tr>
+<tr><td valign=top><em>base</em>&nbsp;</td><td>
+Radix number of number. </td></tr>
+</table>
+</dl> </td>
+ </tr>
+</table>
+<a name="a28" doxytag="triostr.c::trio_to_long_double"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC trio_long_double_t trio_to_long_double </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>source</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>char **&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>endp</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Convert string to floating-point number.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>source</em>&nbsp;</td><td>
+String to be converted. </td></tr>
+<tr><td valign=top><em>endp</em>&nbsp;</td><td>
+Pointer to end of the converted string. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+A floating-point number.</dl>The following Extended Backus-Naur form is used <div class="fragment"><pre>
+ double ::= [ &lt;sign&gt; ]
+ ( &lt;number&gt; |
+ &lt;number&gt; &lt;decimal_point&gt; &lt;number&gt; |
+ &lt;decimal_point&gt; &lt;number&gt; )
+ [ &lt;exponential&gt; [ &lt;sign&gt; ] &lt;number&gt; ]
+ number ::= 1*( &lt;digit&gt; )
+ digit ::= ( '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' )
+ exponential ::= ( 'e' | 'E' )
+ sign ::= ( '-' | '+' )
+ decimal_point ::= '.'
+ </pre></div> </td>
+ </tr>
+</table>
+<a name="a32" doxytag="triostr.c::trio_to_unsigned_long"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC unsigned long trio_to_unsigned_long </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>string</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>char **&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>endp</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>int&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>base</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Convert string to unsigned integer.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>string</em>&nbsp;</td><td>
+String to be converted. </td></tr>
+<tr><td valign=top><em>endp</em>&nbsp;</td><td>
+Pointer to end of converted string. </td></tr>
+<tr><td valign=top><em>base</em>&nbsp;</td><td>
+Radix number of number. </td></tr>
+</table>
+</dl> </td>
+ </tr>
+</table>
+<a name="a27" doxytag="triostr.c::trio_tokenize"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC char* trio_tokenize </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>string</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>delimiters</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Tokenize string.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>string</em>&nbsp;</td><td>
+String to be tokenized. </td></tr>
+<tr><td valign=top><em>tokens</em>&nbsp;</td><td>
+String containing list of delimiting characters. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Start of new token.</dl><dl compact><dt><b>
+Warning: </b><dd>
+<code>string</code> will be destroyed. </dl> </td>
+ </tr>
+</table>
+<a name="a33" doxytag="triostr.c::trio_upper"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> TRIO_STRING_PUBLIC int trio_upper </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">char *&nbsp;</td>
+ <td class="mdname1" valign="top" nowrap>&nbsp; <em>target</em> </td>
+ <td class="md" valign="top">)&nbsp;</td>
+ <td class="md" nowrap></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Convert the alphabetic letters in the string to upper-case.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>target</em>&nbsp;</td><td>
+The string to be converted. </td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+The number of processed characters (converted or not). </dl> </td>
+ </tr>
+</table>
+<HR>
+<center class="copyright">Copyright (C) 2001 Bj&oslash;rn Reese and Daniel Stenberg.</center>
+</body>
+</html>
diff --git a/trio/html/group___user_defined.html b/trio/html/group___user_defined.html
new file mode 100644
index 00000000..b2507275
--- /dev/null
+++ b/trio/html/group___user_defined.html
@@ -0,0 +1,379 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+ <title>TRIO</title>
+ <link href="trio.css" rel="stylesheet" type="text/css">
+</head>
+<body>
+<!-- Generated by Doxygen 1.2.12 -->
+<center>
+<a class="qindex" href="index.html">Main Page</a> &nbsp; <a class="qindex" href="modules.html">Modules</a> &nbsp; </center>
+<hr><h1>User-defined Formatted Printing Functions.</h1>Functions for using customized formatting specifiers.
+<a href="#_details">More...</a><table border=0 cellpadding=0 cellspacing=0>
+<tr><td colspan=2><br><h2>Functions</h2></td></tr>
+<tr><td nowrap align=right valign=top>trio_pointer_t&nbsp;</td><td valign=bottom><a class="el" href="group___user_defined.html#a0">trio_register</a> (trio_callback_t callback, const char *name)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Register new user-defined specifier.</em> <a href="#a0">More...</a><em></em></font><br><br></td></tr>
+<tr><td nowrap align=right valign=top>void&nbsp;</td><td valign=bottom><a class="el" href="group___user_defined.html#a1">trio_unregister</a> (trio_pointer_t handle)</td></tr>
+<tr><td>&nbsp;</td><td><font size=-1><em>Unregister an existing user-defined specifier.</em> <a href="#a1">More...</a><em></em></font><br><br></td></tr>
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+Functions for using customized formatting specifiers.
+<p>
+<b>SYNOPSIS</b>
+<p>
+<div class="fragment"><pre>
+cc ... -ltrio -lm
+
+#include &lt;trio.h&gt;
+#include &lt;triop.h&gt;
+</pre></div>
+<p>
+<b>DESCRIPTION</b>
+<p>
+This documentation is incomplete.
+<p>
+<b>User-defined</b> <b>Specifier</b>
+<p>
+The user-defined specifier consists of a start character (\074 = '&lt;'), an optional namespace string followed by a namespace separator (\072 = ':'), a format string, and an end character (\076 = '&gt;').
+<p>
+The namespace string can consist of alphanumeric characters, and is used to define a named reference (see below). The namespace is case-sensitive. If no namespace is specified, then we use an unnamed reference (see below).
+<p>
+The format can consist of any character except the end character ('&gt;'), the namespace separator (':'), and the nil character (\000).
+<p>
+Any modifier can be used together with the user-defined specifier.
+<p>
+<b>Registering</b>
+<p>
+A user-defined specifier must be registered before it can be used. Unregistered user-defined specifiers are ignored. The <a class="el" href="group___user_defined.html#a0">trio_register</a> function is used to register a user-defined specifier. It takes two argument, a callback function and a namespace, and it returns a handle. The handle must be used to unregister the specifier later.
+<p>
+The following example registers a user-define specifier with the "my_namespace" namespace:
+<p>
+<div class="fragment"><pre>
+ my_handle = trio_register(my_callback, "my_namespace");
+</pre></div>
+<p>
+There can only be one user-defined specifier with a given namespace. There can be an unlimited number (subject to maximum length of the namespace) of different user-defined specifiers.
+<p>
+Passing NULL as the namespace argument results in an anonymous reference. There can be an unlimited number of anonymous references.
+<p>
+<b>REFERENCES</b>
+<p>
+There are two ways that a registered callback can be called. Either the user-defined specifier must contain the registered namespace in the format string, or the handle is passed as an argument to the formatted printing function.
+<p>
+If the namespace is used, then a user-defined pointer must be passed as an argument:
+<p>
+<div class="fragment"><pre>
+ trio_printf("&lt;my_namespace:format&gt;\n", my_data);
+</pre></div>
+<p>
+If the handle is used, then the user-defined specifier must not contain a namespace. Instead the handle must be passed as an argument, followed by a user-defined pointer:
+<p>
+<div class="fragment"><pre>
+ trio_printf("&lt;format&gt;\n", my_handle, my_data);
+</pre></div>
+<p>
+The two examples above are equivalent.
+<p>
+There must be exactly one user-defined pointer per user-defined specifier. This pointer can be used within the callback function with the trio_get_argument getter function (see below).
+<p>
+The format string is optional. It can be used within the callback function with the trio_get_format getter function.
+<p>
+<b>Anonymous</b> <b>References</b> Anonymous references are specified by passing NULL as the namespace.
+<p>
+The handle must be passed as an argument followed by a user-defined pointer. No namespace can be specified.
+<p>
+<div class="fragment"><pre>
+ anon_handle = trio_register(callback, NULL);
+ trio_printf("&lt;format&gt;\n", anon_handle, my_data);
+</pre></div>
+<p>
+<b>Restrictions</b>
+<p>
+<ul>
+<li> The length of the namespace string cannot exceed 63 characters. <li> The length of the user-defined format string cannot exceed 255 characters. <li> User-defined formatting cannot re-define existing specifiers. This restriction was imposed because the existing formatting specifiers have a well-defined behaviour, and any re-definition would apply globally to an application (imagine a third-party library changing the behaviour of a specifier that is crusial to your application).</ul>
+<b>CALLBACK</b> <b>FUNCTION</b>
+<p>
+The callback function will be called if a matching user-defined specifier is found within the formatting string. The callback function takes one input parameter, an opaque reference which is needed by the private functions. It returns an <code>int</code>, which is currently ignored. The prototype is
+<p>
+<div class="fragment"><pre>
+ int (*trio_callback_t)(void *ref);
+</pre></div>
+<p>
+See the Example section for full examples.
+<p>
+<b>PRINTING</b> <b>FUNCTIONS</b>
+<p>
+The following printing functions must only be used inside a callback function. These functions will print to the same output medium as the printf function which invoked the callback function. For example, if the user-defined specifier is used in an sprintf function, then these print functions will output their result to the same string.
+<p>
+<b>Elementary</b> <b>Printing</b>
+<p>
+There are a number of function to print elementary data types.
+<p>
+<ul>
+<li> trio_print_int Print a signed integer. For example: <div class="fragment"><pre>
+ trio_print_int(42);
+</pre></div> <li> trio_print_uint Print an unsigned integer. <li> trio_print_double Print a floating-point number. <li> trio_print_string Print a string. For example: <div class="fragment"><pre>
+ trio_print_string("Hello World");
+ trio_print_string(trio_get_format());
+</pre></div> <li> trio_print_pointer Print a pointer.</ul>
+<b>Formatted</b> <b>Printing</b>
+<p>
+The functions trio_print_ref, trio_vprint_ref, and trio_printv_ref outputs a formatted string just like its printf equivalents.
+<p>
+<div class="fragment"><pre>
+ trio_print_ref(ref, "There are %d towels\n", 42);
+ trio_print_ref(ref, "%&lt;recursive&gt;\n", recursive_writer, trio_get_argument());
+</pre></div>
+<p>
+<b>GETTER</b> <b>AND</b> <b>SETTER</b> <b>FUNCTIONS</b>
+<p>
+The following getter and setter functions must only be used inside a callback function. They can either operate on the modifiers or on special data.
+<p>
+<b>Modifiers</b>
+<p>
+The value of a modifier, or a boolean indication of its presence or absence, can be found or set with the getter and setter functions. The generic prototypes of the these getter and setter functions are
+<p>
+<div class="fragment"><pre>
+ int trio_get_???(void *ref);
+ void trio_set_???(void *ref, int);
+</pre></div>
+<p>
+where ??? <code>refers</code> to a modifier. For example, to get the width of the user-defined specifier use
+<p>
+<div class="fragment"><pre>
+ int width = trio_get_width(ref);
+</pre></div>
+<p>
+<b>Special</b> <b>Data</b>
+<p>
+Consider the following user-defined specifier, in its two possible referencing presentations.
+<p>
+<div class="fragment"><pre>
+ trio_printf("%&lt;format&gt;\n", namespace_writer, argument);
+ trio_printf("%&lt;namespace:format&gt;\n", argument);
+</pre></div>
+<p>
+trio_get_format will get the <code>format</code> string, and trio_get_argument} will get the <code>argument</code> parameter. There are no associated setter functions.
+<p>
+<b>EXAMPLES</b>
+<p>
+The following examples show various types of user-defined specifiers. Although each specifier is demonstrated in isolation, they can all co-exist within the same application.
+<p>
+<b>Time</b> <b>Example</b>
+<p>
+Print the time in the format "HOUR:MINUTE:SECOND" if "time" is specified inside the user-defined specifier.
+<p>
+<div class="fragment"><pre>
+ static int time_writer(void *ref)
+ {
+ const char *format;
+ time_t *data;
+ char buffer[256];
+
+ format = trio_get_format(ref);
+ if ((format) &amp;&amp; (strcmp(format, "time") == 0)) {
+ data = trio_get_argument(ref);
+ if (data == NULL)
+ return -1;
+ strftime(buffer, sizeof(buffer), "%H:%M:%S", localtime(data));
+ trio_print_string(ref, buffer);
+ }
+ return 0;
+ }
+</pre></div>
+<p>
+<div class="fragment"><pre>
+ int main(void)
+ {
+ void *handle;
+ time_t now = time(NULL);
+
+ handle = trio_register(time_print, "my_time");
+
+ trio_printf("%&lt;time&gt;\n", handle, &amp;now);
+ trio_printf("%&lt;my_time:time&gt;\n", &amp;now);
+
+ trio_unregister(handle);
+ return 0;
+ }
+</pre></div>
+<p>
+<b>Complex</b> <b>Numbers</b> <b>Example</b>
+<p>
+Consider a complex number consisting of a real part, re, and an imaginary part, im.
+<p>
+<div class="fragment"><pre>
+ struct Complex {
+ double re;
+ double im;
+ };
+</pre></div>
+<p>
+This example can print such a complex number in one of two formats. The default format is "re + i im". If the alternative modifier is used, then the format is "r exp(i theta)", where r is the length of the complex vector (re, im) and theta is its angle.
+<p>
+<div class="fragment"><pre>
+ static int complex_print(void *ref)
+ {
+ struct Complex *data;
+ const char *format;
+
+ data = (struct Complex *)trio_get_argument(ref);
+ if (data) {
+ format = trio_get_format(ref);
+
+ if (trio_get_alternative(ref)) {
+ double r, theta;
+
+ r = sqrt(pow(data-&gt;re, 2) + pow(data-&gt;im, 2));
+ theta = acos(data-&gt;re / r);
+ trio_print_ref(ref, "%#f exp(i %#f)", r, theta);
+
+ } else {
+ trio_print_ref(ref, "%#f + i %#f", data-&gt;re, data-&gt;im);
+ }
+ }
+ return 0;
+ }
+</pre></div>
+<p>
+<div class="fragment"><pre>
+ int main(void)
+ {
+ void *handle;
+
+ handle = trio_register(complex_print, "complex");
+
+ /* Normal format. With handle and the with namespace */
+ trio_printf("%&lt;&gt;\n", handle, &amp;complex);
+ trio_printf("%&lt;complex:&gt;\n", &amp;complex);
+ /* In exponential notation */
+ trio_printf("%#&lt;&gt;\n", handle, &amp;complex);
+ trio_printf("%#&lt;complex:unused data&gt;\n", &amp;complex);
+
+ trio_unregister(handle);
+ return 0;
+ }
+</pre></div>
+<p>
+<b>RETURN</b> <b>VALUES</b>
+<p>
+<a class="el" href="group___user_defined.html#a0">trio_register</a> returns a handle, or NULL if an error occured.
+<p>
+<b>SEE</b> <b>ALSO</b>
+<p>
+<a class="el" href="group___printf.html#a0">trio_printf</a>
+<p>
+<b>NOTES</b>
+<p>
+User-defined specifiers, <a class="el" href="group___user_defined.html#a0">trio_register</a>, and <a class="el" href="group___user_defined.html#a1">trio_unregister</a> are not thread-safe. In multi-threaded applications they must be guarded by mutexes. Trio provides two special callback functions, called ":enter" and ":leave", which are invoked every time a thread-unsafe operation is attempted. As the thread model is determined by the application, these callback functions must be implemented by the application.
+<p>
+The following callback functions are for demonstration-purposes only. Replace their bodies with locking and unlocking of a mutex to achieve thread-safety. <div class="fragment"><pre>
+ static int enter_region(void *ref)
+ {
+ fprintf(stderr, "Enter Region\n");
+ return 1;
+ }
+
+ static int leave_region(void *ref)
+ {
+ fprintf(stderr, "Leave Region\n");
+ return 1;
+ }
+</pre></div> These two callbacks must be registered before other callbacks are registered. <div class="fragment"><pre>
+ trio_register(enter_region, ":enter");
+ trio_register(leave_region, ":leave");
+
+ another_handle = trio_register(another_callback, NULL);
+</pre></div> <hr><h2>Function Documentation</h2>
+<a name="a0" doxytag="trio.c::trio_register"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> trio_pointer_t trio_register </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">trio_callback_t&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>callback</em>, </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td class="md" nowrap>const char *&nbsp;</td>
+ <td class="mdname" nowrap>&nbsp; <em>name</em></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Register new user-defined specifier.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>callback</em>&nbsp;</td><td>
+</td></tr>
+<tr><td valign=top><em>name</em>&nbsp;</td><td>
+</td></tr>
+</table>
+</dl><dl compact><dt><b>
+Returns: </b><dd>
+Handle. </dl> </td>
+ </tr>
+</table>
+<a name="a1" doxytag="trio.c::trio_unregister"></a><p>
+<table width="100%" cellpadding="2" cellspacing="0" border="0">
+ <tr>
+ <td class="md">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top"> void trio_unregister </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">trio_pointer_t&nbsp;</td>
+ <td class="mdname1" valign="top" nowrap>&nbsp; <em>handle</em> </td>
+ <td class="md" valign="top">)&nbsp;</td>
+ <td class="md" nowrap></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing=5 cellpadding=0 border=0>
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Unregister an existing user-defined specifier.
+<p>
+<dl compact><dt><b>
+Parameters: </b><dd>
+<table border=0 cellspacing=2 cellpadding=0>
+<tr><td valign=top><em>handle</em>&nbsp;</td><td>
+</td></tr>
+</table>
+</dl> </td>
+ </tr>
+</table>
+<HR>
+<center class="copyright">Copyright (C) 2001 Bj&oslash;rn Reese and Daniel Stenberg.</center>
+</body>
+</html>
diff --git a/trio/html/index.html b/trio/html/index.html
new file mode 100644
index 00000000..124ad017
--- /dev/null
+++ b/trio/html/index.html
@@ -0,0 +1,88 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+ <title>TRIO</title>
+ <link href="trio.css" rel="stylesheet" type="text/css">
+</head>
+<body>
+<!-- Generated by Doxygen 1.2.12 -->
+<center>
+<a class="qindex" href="index.html">Main Page</a> &nbsp; <a class="qindex" href="modules.html">Modules</a> &nbsp; </center>
+<hr><h1>TRIO Documentation</h1>
+<p>
+ <dl compact><dt><b>
+Author: </b><dd>
+Bjørn Reese , Daniel Stenberg</dl><a name="intro"><h2>Introduction</h2></a>
+
+<p>
+Trio is a fully matured and stable set of printf and string functions designed be used by applications with focus on portability or with the need for additional features that are not supported by standard stdio implementation.
+<p>
+There are several cases where you may want to consider using trio:
+<p>
+<ul>
+<li> Portability across heterogeneous platforms. <li> Embedded systems without stdio support. <li> Extendability of unsupported features. <li> Your native version does not do everything you need.</ul>
+When you write applications that must be portable to a wide range of platforms you often have to deal with inadequate implementations of the stdio library functions. Most notably is the lack of secure formatting functions, such as snprintf, or the lack of parameter reordering commonly used for the internationalization of applications, such as the &lt;num&gt;$ modifier. Sometimes the feature you need is simply not present in stdio. So you end up spending much effort on determining which platforms supports what, and to write your own versions of various features. This is where trio can help you. Trio is a platform-independent implementation of the stdio printf and scanf functions and the string library functions.
+<p>
+The functionality described in the stdio standards is a compromise, and does unfortunately not include a mechanism to extend the functionality for an individual application. Oftentimes an application has the need for an extra feature, and the application code can become much more clear and readable by using an extension mechanism. Trio supports a range of useful extensions such as user-defined specifiers, passing of arguments in arrays, localized string scanning, thousand-separators, and arbitrary integer bases.
+<p>
+Trio fully implements the C99 (ISO/IEC 9899:1999) and UNIX98 (the Single Unix Specification, Version 2) standards, as well as many features from other implemenations, e.g. the GNU libc and BSD4.
+<p>
+<a name="examples"><h2>Examples</h2></a>
+
+<p>
+<a name="ex1"><h3>Binary Numbers</h3></a>
+ Output an integer as a binary number using a trio extension. <div class="fragment"><pre>
+ trio_printf("%..2i\n", number);
+</pre></div>
+<p>
+<a name="ex2"><h3>Thousand-separator</h3></a>
+ Output a number with thousand-separator using a trio extension. <div class="fragment"><pre>
+ trio_printf("%'f\n", 12345.6);
+</pre></div> The thousand-separator described by the locale is used.
+<p>
+<a name="ex3"><h3>Fixed Length Array and Sticky Modifier</h3></a>
+ Output an fixed length array of floating-point numbers. <div class="fragment"><pre>
+ double array[] = {1.0, 2.0, 3.0};
+ printf("%.2f %.2f %.2f\n", array[0], array[1], array[2]);
+</pre></div> The same with two trio extensions (arguments are passed in an array, and the first formatting specifier sets the sticky option so we do not have to type all the formatting modifiers for the remaining formatting specifiers) <div class="fragment"><pre>
+ trio_printfv("%!.2f %f %f\n", array);
+</pre></div> Another, and more powerful, application of being able to pass arguments in an array is the creation of the printf/scanf statement at run-time, where the formatting string, and thus the argument list, is based on an external configuration file.
+<p>
+<a name="ex4"><h3>Localized scanning</h3></a>
+ Parse a string consisting of one or more upper-case alphabetic characters followed by one or more numeric characters. <div class="fragment"><pre>
+ sscanf(buffer, "%[A-Z]%[0-9]", alphabetic, numeric);
+</pre></div> The same but with locale using a trio extension. <div class="fragment"><pre>
+ trio_sscanf(buffer, "%[[:upper:]]%[[:digit:]]", alphabetic, numeric);
+</pre></div>
+<p>
+<a name="legal"><h2>Legal Issues</h2></a>
+ Trio is distributed under the following license, which allows practically anybody to use it in almost any kind of software, including proprietary software, without difficulty.
+<p>
+"Copyright (C) 1998-2001 Bjorn Reese and Daniel Stenberg.
+<p>
+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.
+<p>
+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."
+<p>
+<a name="contribution"><h2>Contribution</h2></a>
+
+<p>
+<a name="contribute"><h3>Contribute</h3></a>
+ We appreciate any type of contribution, from ideas over improvements to error corrections.
+<p>
+The project space contains references to bug and feature tracking, mailing-list, and the CVS repository. We prefer communication via the mailing-list, but do not require you to be subscribed, because trio is a small project.
+<p>
+The project space is located at <a href="http://sourceforge.net/projects/ctrio/">http://sourceforge.net/projects/ctrio/</a>
+<p>
+<a name="contributors"><h3>Contributors</h3></a>
+ We have received contributions from the following persons (in alphabetic order sorted by surname)
+<p>
+<ul>
+<li> Craig Berry <li> Stan Boehm <li> Robert Collins <li> Danny Dulai <li> John Fotheringham <li> Markus Henke <li> Ken Gibson <li> Paul Janzen <li> Richard Jinks <li> Tero Jänkä <li> Howard Kapustein <li> Mehdi Lavasani <li> Alexander Lukyanov <li> Emmanuel Mogenet <li> Jacob Navia <li> Jose Ortiz <li> Joe Orton <li> Gisli Ottarsson <li> Marc Werwerft <li> Igor Zlatkovic</ul>
+Please let us know, and accept our apology, if we have omitted anybody.
+<p>
+<HR>
+<center class="copyright">Copyright (C) 2001 Bj&oslash;rn Reese and Daniel Stenberg.</center>
+</body>
+</html>
diff --git a/trio/html/modules.html b/trio/html/modules.html
new file mode 100644
index 00000000..49885970
--- /dev/null
+++ b/trio/html/modules.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+ <title>TRIO</title>
+ <link href="trio.css" rel="stylesheet" type="text/css">
+</head>
+<body>
+<!-- Generated by Doxygen 1.2.12 -->
+<center>
+<a class="qindex" href="index.html">Main Page</a> &nbsp; <a class="qindex" href="modules.html">Modules</a> &nbsp; </center>
+<hr><h1>TRIO Modules</h1>Here is a list of all modules:<ul>
+<li><a class="el" href="group___printf.html">Formatted Printing Functions.</a>
+<li><a class="el" href="group___user_defined.html">User-defined Formatted Printing Functions.</a>
+<li><a class="el" href="group___scanf.html">Formatted Scanning Functions.</a>
+<li><a class="el" href="group___special_quantities.html">Special Quantifies.</a>
+<li><a class="el" href="group___static_strings.html">Static String Functions.</a>
+<li><a class="el" href="group___dynamic_strings.html">Dynamic String Functions.</a>
+</ul>
+<HR>
+<center class="copyright">Copyright (C) 2001 Bj&oslash;rn Reese and Daniel Stenberg.</center>
+</body>
+</html>
diff --git a/trio/html/trio.css b/trio/html/trio.css
new file mode 100644
index 00000000..1b3a9926
--- /dev/null
+++ b/trio/html/trio.css
@@ -0,0 +1,35 @@
+/* HTML tags */
+
+BODY {
+ background-color: white;
+ color: darkblue;
+}
+
+TD { color: darkblue; }
+
+H1 { text-align: center; }
+
+H3 { font-style: italic; }
+
+HR {
+ width: 85%;
+ align: center;
+}
+
+.copyright { color: darkblue; }
+
+/* Links */
+
+:link { color: blue; }
+
+:visited { color: purple; }
+
+:active { color: red; }
+
+.el:link { font-style: italic; }
+
+/* Examples */
+
+DIV.fragment {
+ color: maroon;
+}
diff --git a/trio/install-sh b/trio/install-sh
new file mode 100755
index 00000000..e8436696
--- /dev/null
+++ b/trio/install-sh
@@ -0,0 +1,250 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/trio/libtrio.a b/trio/libtrio.a
new file mode 100644
index 00000000..f58fe277
--- /dev/null
+++ b/trio/libtrio.a
Binary files differ
diff --git a/trio/maketgz b/trio/maketgz
new file mode 100755
index 00000000..aed8cf50
--- /dev/null
+++ b/trio/maketgz
@@ -0,0 +1,46 @@
+#! /bin/sh
+# Script to build archives with
+#
+
+echo "Version number?"
+read version
+
+# get current dir
+dir=`pwd`
+
+# Get basename
+orig=`basename $dir`
+
+# Get the left part of the dash (-)
+new=`echo $orig | cut -d- -f1`
+
+# Build new directory name
+n=$new-$version;
+
+# Tell the world what we're doing
+echo "creates $n.tar.gz";
+
+if [ -r $n ]; then
+ echo "Directory already exists!"
+ exit
+fi
+
+# Create the new dir
+mkdir $n
+
+# Copy all relevant files, with path and permissions!
+tar -cf - `cat FILES` | (cd $n; tar -xBpf -) || exit 1
+
+(cd $n && sh autogen.sh) || exit 1
+
+# Make a tar archive of it all
+tar -cvf $n.tar $n
+
+# gzip the archive
+gzip $n.tar
+
+# Make it world readable
+chmod a+r $n.tar.gz ;
+
+# Delete the temp dir
+rm -rf $n
diff --git a/trio/regression b/trio/regression
new file mode 100755
index 00000000..f1d0df7e
--- /dev/null
+++ b/trio/regression
Binary files differ
diff --git a/trio/regression.c b/trio/regression.c
new file mode 100644
index 00000000..ccbd78b5
--- /dev/null
+++ b/trio/regression.c
@@ -0,0 +1,1206 @@
+/*************************************************************************
+ * Regression test
+ */
+
+#include "triodef.h"
+#if defined(TRIO_COMPILER_ANCIENT)
+# include <varargs.h>
+#else
+# include <stdarg.h>
+#endif
+#include <math.h>
+#include <limits.h>
+#include <float.h>
+#include <errno.h>
+
+#include "trio.h"
+#include "triop.h"
+#include "trionan.h"
+#if defined(TRIO_MINIMAL)
+# define TRIO_STRING_PUBLIC static
+# include "triostr.c"
+#else
+# include "triostr.h"
+#endif
+#undef printf
+
+#if TRIO_WIDECHAR
+# include <wchar.h>
+#endif
+
+#define QUOTE(x) #x
+
+#define DOUBLE_EQUAL(x,y) (((x)>(y)-DBL_EPSILON) && ((x)<(y)+DBL_EPSILON))
+#define FLOAT_EQUAL(x,y) (((x)>(y)-FLT_EPSILON) && ((x)<(y)+FLT_EPSILON))
+
+static TRIO_CONST char rcsid[] = "@(#)$Id: regression.c,v 1.44 2002/12/29 15:08:56 breese Exp $";
+
+
+/*************************************************************************
+ *
+ */
+static void
+Dump
+TRIO_ARGS2((buffer, rc),
+ char *buffer,
+ int rc)
+{
+ if (rc < 0)
+ {
+ printf("Err = %d (%s), Pos = %d\n",
+ TRIO_ERROR_CODE(rc),
+ TRIO_ERROR_NAME(rc),
+ TRIO_ERROR_POSITION(rc));
+ }
+ else if (buffer)
+ printf("buffer[% 3d] = \"%s\"\n", rc, buffer);
+}
+
+/*************************************************************************
+ *
+ */
+static void
+Report0
+TRIO_ARGS2((file, line),
+ TRIO_CONST char *file,
+ int line)
+{
+ printf("Verification failed in %s:%d.\n", file, line);
+}
+
+/*************************************************************************
+ *
+ */
+static void
+Report
+TRIO_ARGS4((file, line, expected, got),
+ TRIO_CONST char *file,
+ int line,
+ TRIO_CONST char *expected,
+ TRIO_CONST char *got)
+{
+ Report0(file, line);
+ printf(" Expected \"%s\"\n", expected);
+ printf(" Got \"%s\"\n", got);
+}
+
+/*************************************************************************
+ *
+ */
+int
+Verify
+TRIO_VARGS5((file, line, result, fmt, va_alist),
+ TRIO_CONST char *file,
+ int line,
+ TRIO_CONST char *result,
+ TRIO_CONST char *fmt,
+ TRIO_VA_DECL)
+{
+ int rc;
+ va_list args;
+ char buffer[4096];
+
+ TRIO_VA_START(args, fmt);
+ rc = trio_vsnprintf(buffer, sizeof(buffer), fmt, args);
+ if (rc < 0)
+ Dump(buffer, rc);
+ TRIO_VA_END(args);
+
+ if (!trio_equal_case(result, buffer))
+ {
+ Report(file, line, result, buffer);
+ return 1;
+ }
+ return 0;
+}
+
+/*************************************************************************
+ *
+ */
+int
+VerifyReturnValues(TRIO_NOARGS)
+{
+ int nerrors = 0;
+ int rc;
+ int count;
+ char *expected;
+ char buffer[4096];
+ char result[4096];
+
+ rc = trio_sprintf(buffer, "%s%n", "0123456789", &count);
+ trio_sprintf(result, "%d %d %s", rc, count, buffer);
+ expected = "10 10 0123456789";
+ if (!trio_equal_case(result, expected))
+ {
+ nerrors++;
+ Report(__FILE__, __LINE__, expected, result);
+ }
+
+ rc = trio_snprintf(buffer, sizeof(buffer), "%s%n", "0123456789", &count);
+ trio_sprintf(result, "%d %d %s", rc, count, buffer);
+ expected = "10 10 0123456789";
+ if (!trio_equal_case(result, expected))
+ {
+ nerrors++;
+ Report(__FILE__, __LINE__, expected, result);
+ }
+
+ rc = trio_snprintf(buffer, 4, "%s%n", "0123456789", &count);
+ trio_sprintf(result, "%d %d %s", rc, count, buffer);
+ expected = "10 3 012";
+ if (!trio_equal_case(result, expected))
+ {
+ nerrors++;
+ Report(__FILE__, __LINE__, expected, result);
+ }
+
+ /* The output buffer contains the empty string */
+ rc = trio_snprintf(buffer, 1, "%s%n", "0123456789", &count);
+ trio_sprintf(result, "%d %d %s", rc, count, buffer);
+ expected = "10 0 ";
+ if (!trio_equal_case(result, expected))
+ {
+ nerrors++;
+ Report(__FILE__, __LINE__, expected, result);
+ }
+
+ /* The output buffer should be left untouched when max size is 0 */
+ trio_sprintf(buffer, "DO NOT TOUCH");
+ rc = trio_snprintf(buffer, 0, "%s%n", "0123456789", &count);
+ trio_sprintf(result, "%d %d %s", rc, count, buffer);
+ expected = "10 0 DO NOT TOUCH";
+ if (!trio_equal_case(result, expected))
+ {
+ nerrors++;
+ Report(__FILE__, __LINE__, expected, result);
+ }
+
+ return nerrors;
+}
+
+/*************************************************************************
+ *
+ */
+#define TEST_STRING "0123456789"
+
+int
+VerifyAllocate(TRIO_NOARGS)
+{
+ int nerrors = 0;
+ int rc;
+ char *string;
+ int count;
+ int test_size = sizeof(TEST_STRING) - 1;
+
+ /* Allocate a string with the result */
+ rc = trio_asprintf(&string, "%s%n", TEST_STRING, &count);
+ if (rc < 0)
+ {
+ nerrors++;
+ Dump(string, rc);
+ }
+ else if (count != test_size)
+ {
+ nerrors++;
+ printf("Validation failed in %s:%d\n", __FILE__, __LINE__);
+ printf(" Expected %%n = %d\n", test_size);
+ printf(" Got %%n = %d\n", count);
+ }
+ else if (!trio_equal_case(string, TEST_STRING))
+ {
+ nerrors++;
+ Report(__FILE__, __LINE__, TEST_STRING, string);
+ }
+ if (string)
+ free(string);
+
+ return nerrors;
+}
+
+
+/*************************************************************************
+ *
+ */
+int
+VerifyFormatting(TRIO_NOARGS)
+{
+ int nerrors = 0;
+ char buffer[256];
+
+ /* Normal text */
+ nerrors += Verify(__FILE__, __LINE__, "Hello world",
+ "Hello world");
+ /* String */
+ nerrors += Verify(__FILE__, __LINE__, "Hello world",
+ "%s", "Hello world");
+ /* Pointer */
+ if (sizeof(void *) == 4)
+ {
+ nerrors += Verify(__FILE__, __LINE__, "Pointer 0x01234567",
+ "Pointer %p", 0x1234567);
+ }
+ else if (sizeof(void *) == 8)
+ {
+ nerrors += Verify(__FILE__, __LINE__, "Pointer 0x0123456789012345",
+ "Pointer %p", 0x123456789012345);
+ }
+ /* Nil pointer */
+ nerrors += Verify(__FILE__, __LINE__, "Pointer (nil)",
+ "Pointer %p", NULL);
+ /* Integer */
+ nerrors += Verify(__FILE__, __LINE__, "Number 42",
+ "Number %d", 42);
+ nerrors += Verify(__FILE__, __LINE__, "Number -42",
+ "Number %d", -42);
+ nerrors += Verify(__FILE__, __LINE__, "Number 42",
+ "Number %ld", 42L);
+ nerrors += Verify(__FILE__, __LINE__, "Number -42",
+ "Number %ld", -42L);
+ /* Integer width */
+ nerrors += Verify(__FILE__, __LINE__, " 1234",
+ "%6d", 1234);
+ nerrors += Verify(__FILE__, __LINE__, " 1234",
+ "%*d", 6, 1234);
+ /* Integer width overrun */
+ nerrors += Verify(__FILE__, __LINE__, "123456",
+ "%4d", 123456);
+ /* Integer precision */
+ nerrors += Verify(__FILE__, __LINE__, "0012",
+ "%.4d", 12);
+ nerrors += Verify(__FILE__, __LINE__, "0012",
+ "%.*d", 4, 12);
+ nerrors += Verify(__FILE__, __LINE__, " 0012",
+ "%6.*d", 4, 12);
+ nerrors += Verify(__FILE__, __LINE__, " 0012",
+ "%*.*d", 6, 4, 12);
+ nerrors += Verify(__FILE__, __LINE__, " 0012",
+ "%*.*.*d", 6, 4, 2, 12);
+ nerrors += Verify(__FILE__, __LINE__, " 0012",
+ "%*.*.*i", 6, 4, 10, 12);
+ /* Integer sign, zero-padding, and width */
+ nerrors += Verify(__FILE__, __LINE__, "+01234",
+ "%+06d", 1234);
+ nerrors += Verify(__FILE__, __LINE__, " 01234",
+ "% 06d", 1234);
+ nerrors += Verify(__FILE__, __LINE__, "+01234",
+ "% +06d", 1234);
+ /* Integer adjust, zero-padding, and width */
+ nerrors += Verify(__FILE__, __LINE__, "12 ",
+ "%-08d", 12);
+ /* Integer zero-padding, width, and precision */
+ nerrors += Verify(__FILE__, __LINE__, " 000012",
+ "%08.6d", 12);
+ /* Integer base */
+ nerrors += Verify(__FILE__, __LINE__, "42",
+ "%u", 42);
+ nerrors += Verify(__FILE__, __LINE__, "-1",
+ "%d", -1);
+ nerrors += Verify(__FILE__, __LINE__, "52",
+ "%o", 42);
+ nerrors += Verify(__FILE__, __LINE__, "052",
+ "%#o", 42);
+ nerrors += Verify(__FILE__, __LINE__, "0",
+ "%#o", 0);
+ nerrors += Verify(__FILE__, __LINE__, "2a",
+ "%x", 42);
+ nerrors += Verify(__FILE__, __LINE__, "2A",
+ "%X", 42);
+ nerrors += Verify(__FILE__, __LINE__, "0x2a",
+ "%#x", 42);
+ nerrors += Verify(__FILE__, __LINE__, "0X2A",
+ "%#X", 42);
+ nerrors += Verify(__FILE__, __LINE__, "0x00c ",
+ "%-#6.3x", 12);
+ nerrors += Verify(__FILE__, __LINE__, "",
+ "%.d", 0);
+ nerrors += Verify(__FILE__, __LINE__, "",
+ "%#.d", 0);
+ nerrors += Verify(__FILE__, __LINE__, "42",
+ "%.d", 42);
+ nerrors += Verify(__FILE__, __LINE__, "",
+ "%.o", 0);
+ nerrors += Verify(__FILE__, __LINE__, " 0000",
+ "%8.4o", 0);
+ nerrors += Verify(__FILE__, __LINE__, " 0",
+ "%8o", 0);
+ nerrors += Verify(__FILE__, __LINE__, "00000000",
+ "%08o", 0);
+ nerrors += Verify(__FILE__, __LINE__, "0",
+ "%#.o", 0);
+ nerrors += Verify(__FILE__, __LINE__, "52",
+ "%.o", 42);
+ nerrors += Verify(__FILE__, __LINE__, "",
+ "%.x", 0);
+ nerrors += Verify(__FILE__, __LINE__, "",
+ "%#.x", 0);
+ nerrors += Verify(__FILE__, __LINE__, "2a",
+ "%.x", 42);
+ sprintf(buffer, "%u", UINT_MAX);
+ nerrors += Verify(__FILE__, __LINE__, buffer,
+ "%u", -1);
+ sprintf(buffer, "%x", UINT_MAX);
+ nerrors += Verify(__FILE__, __LINE__, buffer,
+ "%x", -1);
+ /* Double */
+ nerrors += Verify(__FILE__, __LINE__, "3141.000000",
+ "%f", 3141.0);
+ nerrors += Verify(__FILE__, __LINE__, "3141.500000",
+ "%f", 3141.5);
+ nerrors += Verify(__FILE__, __LINE__, "3.141000e+03",
+ "%e", 3141.0);
+ nerrors += Verify(__FILE__, __LINE__, " -2.3420e-02",
+ "%16.4e", -2.342E-02);
+ nerrors += Verify(__FILE__, __LINE__, " -2.3420e-22",
+ "%16.4e", -2.342E-22);
+ nerrors += Verify(__FILE__, __LINE__, " 2.3420e-02",
+ "% 16.4e", 2.342E-02);
+ nerrors += Verify(__FILE__, __LINE__, " 2.3420e-02",
+ "% 1.4e", 2.342E-02);
+ nerrors += Verify(__FILE__, __LINE__, "3.141000E-44",
+ "%E", 3.141e-44);
+ nerrors += Verify(__FILE__, __LINE__, "0",
+ "%g", 0.0);
+ nerrors += Verify(__FILE__, __LINE__, "-0",
+ "%g", trio_nzero());
+ nerrors += Verify(__FILE__, __LINE__, "3141.5",
+ "%g", 3141.5);
+ nerrors += Verify(__FILE__, __LINE__, "3.1415E-06",
+ "%G", 3.1415e-6);
+ nerrors += Verify(__FILE__, __LINE__, "+3141.000000",
+ "%+f", 3141.0);
+ nerrors += Verify(__FILE__, __LINE__, "-3141.000000",
+ "%+f", -3141.0);
+ nerrors += Verify(__FILE__, __LINE__, "0.333333",
+ "%f", 1.0/3.0);
+ nerrors += Verify(__FILE__, __LINE__, "0.666667",
+ "%f", 2.0/3.0);
+ /* Beyond accuracy */
+ nerrors += Verify(__FILE__, __LINE__, "0.000000",
+ "%f", 1.234567890123456789e-20);
+#if defined(TRIO_BREESE)
+ nerrors += Verify(__FILE__, __LINE__, "1.3999999999999999111821580299875",
+ "%.32g", 1.4);
+ nerrors += Verify(__FILE__, __LINE__, "1.39999999999999991118215802998748",
+ "%.32f", 1.4);
+ nerrors += Verify(__FILE__, __LINE__, "1.3999999999999999111821580300",
+ "%.28f", 1.4);
+ nerrors += Verify(__FILE__, __LINE__, "1.399999999999999911182158",
+ "%.24f", 1.4);
+ nerrors += Verify(__FILE__, __LINE__, "1.39999999999999991",
+ "%.17f", 1.4);
+ nerrors += Verify(__FILE__, __LINE__, "1.40000000000000",
+ "%.14f", 1.4);
+ nerrors += Verify(__FILE__, __LINE__, "39413.800000000002910383045673370361",
+ "%.30f", 39413.80);
+#endif
+ /* 2^-1 + 2^-15 */
+ nerrors += Verify(__FILE__, __LINE__, "0.500030517578125",
+ "%.*g", DBL_DIG + 10, 0.500030517578125);
+ /* Double decimal point */
+ nerrors += Verify(__FILE__, __LINE__, "3141",
+ "%.0f", 3141.0);
+ nerrors += Verify(__FILE__, __LINE__, "3142",
+ "%.0f", 3141.5);
+ nerrors += Verify(__FILE__, __LINE__, "3141",
+ "%.f", 3141.0);
+ nerrors += Verify(__FILE__, __LINE__, "12",
+ "%.f", 12.34);
+ nerrors += Verify(__FILE__, __LINE__, "3141.000",
+ "%.3f", 3141.0);
+ nerrors += Verify(__FILE__, __LINE__, "3141.000000",
+ "%#f", 3141.0);
+ nerrors += Verify(__FILE__, __LINE__, "0.0000",
+ "%#.4f", 0.0);
+ nerrors += Verify(__FILE__, __LINE__, "0.000",
+ "%#.4g", 0.0);
+ nerrors += Verify(__FILE__, __LINE__, "3141.0000",
+ "%#.4f", 3141.0);
+ nerrors += Verify(__FILE__, __LINE__, "3141.",
+ "%#.0f", 3141.0);
+ nerrors += Verify(__FILE__, __LINE__, "3141.",
+ "%#.f", 3141.0);
+ nerrors += Verify(__FILE__, __LINE__, "11.0000",
+ "%#.4f", 11.0);
+ nerrors += Verify(__FILE__, __LINE__, "100.00",
+ "%.2f", 99.9999);
+ nerrors += Verify(__FILE__, __LINE__, "3e+03",
+ "%.e", 3141.0);
+ nerrors += Verify(__FILE__, __LINE__, "3.e+03",
+ "%#.e", 3141.0);
+ nerrors += Verify(__FILE__, __LINE__, "100",
+ "%.2g", 99.9999);
+ nerrors += Verify(__FILE__, __LINE__, "100.",
+ "%#.2g", 99.9999);
+ nerrors += Verify(__FILE__, __LINE__, "0.123",
+ "%0g", 0.123);
+ nerrors += Verify(__FILE__, __LINE__, "1.00e+00",
+ "%.2e", 0.9999);
+ nerrors += Verify(__FILE__, __LINE__, "1",
+ "%.2g", 0.9999);
+ nerrors += Verify(__FILE__, __LINE__, "2",
+ "%.g", 1.5);
+ nerrors += Verify(__FILE__, __LINE__, "0.01",
+ "%.2g", 0.01);
+ nerrors += Verify(__FILE__, __LINE__, "0.010",
+ "%#.2g", 0.01);
+ /* Double width, precision, and zero padding */
+ nerrors += Verify(__FILE__, __LINE__, "00003.141500e+03",
+ "%016e", 3141.5);
+ nerrors += Verify(__FILE__, __LINE__, " 3.141500e+03",
+ "%16e", 3141.5);
+ nerrors += Verify(__FILE__, __LINE__, "3.141500e+03 ",
+ "%-16e", 3141.5);
+ nerrors += Verify(__FILE__, __LINE__, "03.142e+03",
+ "%010.3e", 3141.5);
+#if !defined(TRIO_COMPILER_ANCIENT)
+ /* Long double */
+ nerrors += Verify(__FILE__, __LINE__, "1.400000",
+ "%Lf", 1.4L);
+#endif
+
+ /* Special cases */
+ nerrors += Verify(__FILE__, __LINE__, "1.00",
+ "%.2f", 0.999);
+ nerrors += Verify(__FILE__, __LINE__, "100",
+ "%.0f", 99.9);
+ nerrors += Verify(__FILE__, __LINE__, "inf",
+ "%f", trio_pinf());
+ nerrors += Verify(__FILE__, __LINE__, "-inf",
+ "%f", trio_ninf());
+ nerrors += Verify(__FILE__, __LINE__, "INF",
+ "%F", trio_pinf());
+ nerrors += Verify(__FILE__, __LINE__, "-INF",
+ "%F", trio_ninf());
+ /* May fail if NaN is unsupported */
+ nerrors += Verify(__FILE__, __LINE__, "nan",
+ "%f", trio_nan());
+ nerrors += Verify(__FILE__, __LINE__, "NAN",
+ "%F", trio_nan());
+
+ /* Char width alignment */
+ nerrors += Verify(__FILE__, __LINE__, "Char X .",
+ "Char %-4c.", 'X');
+ /* String width / precision */
+ nerrors += Verify(__FILE__, __LINE__, " testing",
+ "%8s", "testing");
+ nerrors += Verify(__FILE__, __LINE__, "testing ",
+ "%-8s", "testing");
+ nerrors += Verify(__FILE__, __LINE__, " testing",
+ "%*s", 8, "testing");
+ nerrors += Verify(__FILE__, __LINE__, "testing ",
+ "%*s", -8, "testing");
+ nerrors += Verify(__FILE__, __LINE__, "test",
+ "%.4s", "testing");
+ nerrors += Verify(__FILE__, __LINE__, "test",
+ "%.*s", 4, "testing");
+ nerrors += Verify(__FILE__, __LINE__, "testing",
+ "%.*s", -4, "testing");
+#if TRIO_UNIX98
+ /* Positional */
+ nerrors += Verify(__FILE__, __LINE__, "222 111",
+ "%2$s %1$s", "111", "222");
+ nerrors += Verify(__FILE__, __LINE__, "123456 12345 0001234 00123",
+ "%4$d %3$*8$d %2$.*7$d %1$*6$.*5$d",
+ 123, 1234, 12345, 123456, 5, 6, 7, 8);
+#endif
+
+#if TRIO_GNU
+ nerrors += Verify(__FILE__, __LINE__, "256",
+ "%Zd", sizeof(buffer));
+ errno = EINTR;
+ nerrors += Verify(__FILE__, __LINE__, "Interrupted system call",
+ "%m");
+#endif
+
+#if TRIO_BSD || TRIO_GNU
+# if defined(TRIO_COMPILER_SUPPORTS_LL)
+ /* This may fail if the preprocessor does not recognize LL */
+ nerrors += Verify(__FILE__, __LINE__, "42",
+ "%qd", 42LL);
+# endif
+#endif
+
+#if TRIO_C99
+ nerrors += Verify(__FILE__, __LINE__, "0x2.ap+4",
+ "%a", 42.0);
+ nerrors += Verify(__FILE__, __LINE__, "-0x2.ap+4",
+ "%a", -42.0);
+ nerrors += Verify(__FILE__, __LINE__, "0x1.8p+0",
+ "%a", 1.5);
+ nerrors += Verify(__FILE__, __LINE__, "0x1.6666666666666p+0",
+ "%a", 1.4);
+ nerrors += Verify(__FILE__, __LINE__, "0xc.45p+8",
+ "%a", 3141.0);
+ nerrors += Verify(__FILE__, __LINE__, "0XC.45P+8",
+ "%A", 3141.0);
+ nerrors += Verify(__FILE__, __LINE__, "0xb.351c434a98fa8p-148",
+ "%a", 3.141e-44);
+ nerrors += Verify(__FILE__, __LINE__, "256",
+ "%zd", sizeof(buffer));
+ nerrors += Verify(__FILE__, __LINE__, "42",
+ "%td", 42);
+# if defined(TRIO_COMPILER_SUPPORTS_LL)
+ /* Some compilers may not handle the LL suffix correctly */
+ nerrors += Verify(__FILE__, __LINE__, "42",
+ "%jd", 42LL);
+# endif
+#endif
+
+#if TRIO_WIDECHAR
+ nerrors += Verify(__FILE__, __LINE__, "Hello World",
+ "%ls", L"Hello World");
+ nerrors += Verify(__FILE__, __LINE__, "\\aHello World",
+ "%#ls", L"\aHello World");
+ nerrors += Verify(__FILE__, __LINE__, "A",
+ "%lc", L'A');
+ nerrors += Verify(__FILE__, __LINE__, "\\a",
+ "%#lc", L'\a');
+#endif
+
+#if TRIO_MICROSOFT
+ nerrors += Verify(__FILE__, __LINE__, "42",
+ "%I8d", 42);
+ nerrors += Verify(__FILE__, __LINE__, "ffffffff",
+ "%I16x", -1);
+#endif
+
+#if TRIO_EXTENSION
+ nerrors += Verify(__FILE__, __LINE__, " 42 86",
+ "%!4d %d", 42, 86);
+ nerrors += Verify(__FILE__, __LINE__, "0042 0086",
+ "%!04d %d", 42, 86);
+ nerrors += Verify(__FILE__, __LINE__, "42",
+ "%&d", sizeof(long), 42L);
+ /* Non-printable string */
+ nerrors += Verify(__FILE__, __LINE__, "NonPrintable \\x01 \\a \\\\",
+ "NonPrintable %#s", "\01 \07 \\");
+ nerrors += Verify(__FILE__, __LINE__, "\\a \\b \\t \\n \\v \\f \\r",
+ "%#s", "\007 \010 \011 \012 \013 \014 \015");
+ /* Quote flag */
+ nerrors += Verify(__FILE__, __LINE__, "Another \"quoted\" string",
+ "Another %'s string", "quoted");
+ /* Integer base */
+ nerrors += Verify(__FILE__, __LINE__, "Number 42 == 1120 (base 3)",
+ "Number %d == %..3i (base 3)", 42, 42);
+ /* Integer base (specifier base must be used instead of base modifier) */
+ nerrors += Verify(__FILE__, __LINE__, "42",
+ "%..3d", 42);
+ nerrors += Verify(__FILE__, __LINE__, "52",
+ "%..3o", 42);
+ nerrors += Verify(__FILE__, __LINE__, "2a",
+ "%..3x", 42);
+ /* Integer thousand separator */
+ nerrors += Verify(__FILE__, __LINE__, "Number 100",
+ "Number %'d", 100);
+ nerrors += Verify(__FILE__, __LINE__, "Number 1,000,000",
+ "Number %'d", 1000000);
+ /* Float thousand separator */
+ nerrors += Verify(__FILE__, __LINE__, "31,415.200000",
+ "%'f", 31415.2);
+ nerrors += Verify(__FILE__, __LINE__, "1,000,000.000000",
+ "%'f", 1000000.0);
+ /* Rounding modifier */
+ nerrors += Verify(__FILE__, __LINE__, "1.4",
+ "%.32Rf", 1.4);
+ nerrors += Verify(__FILE__, __LINE__, "1.4",
+ "%.17Rf", 1.4);
+ nerrors += Verify(__FILE__, __LINE__, "39413.8",
+ "%.30Rf", 39413.80);
+# if !defined(TRIO_COMPILER_ANCIENT)
+ /* Long double */
+ nerrors += Verify(__FILE__, __LINE__, "1.4",
+ "%RLf", 1.4L);
+ nerrors += Verify(__FILE__, __LINE__, "1.4",
+ "%.30RLf", 1.4L);
+# endif
+#endif
+
+#if defined(TRIO_BREESE)
+ /*
+ * These results depends on issues beyond our control. For example,
+ * the accuracy of floating-point numbers depends on the underlying
+ * floating-point hardware (e.g. whether IEEE 754 double or extended-
+ * double format is used).
+ *
+ * These tests are therefore not part of the normal regression test,
+ * but we keep them here for development purposes.
+ */
+ nerrors += Verify(__FILE__, __LINE__, "123456789012345680868.000000",
+ "%f", 1.234567890123456789e20);
+ nerrors += Verify(__FILE__, __LINE__, "1.23456789012345677901e-20",
+ "%.20e", 1.2345678901234567e-20);
+ nerrors += Verify(__FILE__, __LINE__, "0.666666666666666629659233",
+ "%.*g", DBL_DIG + 10, 2.0/3.0);
+ nerrors += Verify(__FILE__, __LINE__, "123456789012345700000",
+ "%Rf", 1.234567890123456789e20);
+# if !defined(TRIO_COMPILER_ANCIENT)
+ nerrors += Verify(__FILE__, __LINE__, "0.666666666666666667",
+ "%RLf", (2.0L/3.0L));
+ nerrors += Verify(__FILE__, __LINE__, "0.666666666666666667",
+ "%.30RLf", (2.0L/3.0L));
+# endif
+#endif
+
+ return nerrors;
+}
+
+/*************************************************************************
+ *
+ */
+int
+VerifyErrors(TRIO_NOARGS)
+{
+ char buffer[512];
+ int rc;
+ int nerrors = 0;
+
+ /* Error: Invalid argument 1 */
+ rc = trio_snprintf(buffer, sizeof(buffer), "%d %r", 42, "text");
+#if TRIO_ERRORS
+ trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d",
+ TRIO_ERROR_CODE(rc),
+ TRIO_ERROR_NAME(rc),
+ TRIO_ERROR_POSITION(rc));
+ nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 5",
+ "%s", buffer);
+#else
+ nerrors += (rc != -1);
+#endif
+ /* Error: Invalid argument 2 */
+ rc = trio_snprintf(buffer, sizeof(buffer), "%#");
+#if TRIO_ERRORS
+ trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d",
+ TRIO_ERROR_CODE(rc),
+ TRIO_ERROR_NAME(rc),
+ TRIO_ERROR_POSITION(rc));
+ nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 3",
+ "%s", buffer);
+#else
+ nerrors += (rc != -1);
+#endif
+ /* Error: Invalid argument 3 */
+ rc = trio_snprintf(buffer, sizeof(buffer), "%hhhd", 42);
+#if TRIO_ERRORS
+ trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d",
+ TRIO_ERROR_CODE(rc),
+ TRIO_ERROR_NAME(rc),
+ TRIO_ERROR_POSITION(rc));
+ nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 4",
+ "%s", buffer);
+#else
+ nerrors += (rc != -1);
+#endif
+ /* Error: Double reference */
+ rc = trio_snprintf(buffer, sizeof(buffer), "hello %1$d %1$d", 31, 32);
+#if TRIO_ERRORS
+ trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d",
+ TRIO_ERROR_CODE(rc),
+ TRIO_ERROR_NAME(rc),
+ TRIO_ERROR_POSITION(rc));
+# if TRIO_UNIX98
+ nerrors += Verify(__FILE__, __LINE__, "Err = 4 (Double reference), Pos = 0",
+ "%s", buffer);
+# else
+ nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 9",
+ "%s", buffer);
+# endif
+#else
+ nerrors += (rc != -1);
+#endif
+ /* Error: Reference gap */
+ rc = trio_snprintf(buffer, sizeof(buffer), "%3$d %1$d", 31, 32, 33);
+#if TRIO_ERRORS
+ trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d",
+ TRIO_ERROR_CODE(rc),
+ TRIO_ERROR_NAME(rc),
+ TRIO_ERROR_POSITION(rc));
+# if TRIO_UNIX98
+ nerrors += Verify(__FILE__, __LINE__, "Err = 5 (Reference gap), Pos = 1",
+ "%s", buffer);
+# else
+ nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 3",
+ "%s", buffer);
+# endif
+#else
+ nerrors += (rc != -1);
+#endif
+
+ return nerrors;
+}
+
+/*************************************************************************
+ *
+ */
+int
+VerifyScanningOneInteger
+TRIO_ARGS5((file, line, expected, format, original),
+ TRIO_CONST char *file,
+ int line,
+ TRIO_CONST char *expected,
+ TRIO_CONST char *format,
+ int original)
+{
+ int number;
+ char data[512];
+
+ trio_snprintf(data, sizeof(data), format, original);
+ trio_sscanf(data, format, &number);
+ return Verify(file, line, expected, format, number);
+}
+
+int
+VerifyScanningIntegers(TRIO_NOARGS)
+{
+ int nerrors = 0;
+
+ nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "42",
+ "%i", 42);
+ nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "42",
+ "%d", 42);
+ nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "-42",
+ "%d", -42);
+ nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "2147483647",
+ "%d", 2147483647);
+ nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "42",
+ "%u", 42);
+ nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "2a",
+ "%x", 42);
+ nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "52",
+ "%o", 42);
+ nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "101010",
+ "%..2i", 42);
+ nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "0x2a",
+ "%#x", 42);
+ nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "052",
+ "%#o", 42);
+
+ return nerrors;
+}
+
+/*************************************************************************
+ *
+ */
+int
+VerifyScanningOneFloat
+TRIO_ARGS5((file, line, expected, format, original),
+ TRIO_CONST char *file,
+ int line,
+ TRIO_CONST char *expected,
+ TRIO_CONST char *format,
+ double original)
+{
+ double number;
+ char data[512];
+
+ trio_snprintf(data, sizeof(data), format, original);
+ trio_sscanf(data, format, &number);
+ return Verify(file, line, expected, format, number);
+}
+
+int
+VerifyScanningFloats(TRIO_NOARGS)
+{
+ int nerrors = 0;
+
+ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "42.000000",
+ "%f", 42.0);
+ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "-42.000000",
+ "%f", -42.0);
+ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "4.200000e+01",
+ "%e", 42.0);
+ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "4.200000E+01",
+ "%E", 42.0);
+ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "42",
+ "%g", 42.0);
+ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.23457e+06",
+ "%g", 1234567.0);
+ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.23457e-06",
+ "%g", 1.234567e-6);
+ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.23457E+06",
+ "%G", 1234567.0);
+ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.234567e+06",
+ "%12e", 1234567.0);
+ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.234500e+00",
+ "%6e", 1234567.0);
+ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.234567e+06",
+ "%.6e", 1234567.0);
+ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.2345670000e+06",
+ "%.10e", 1234567.0);
+ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.23457e+06",
+ "%.6g", 1234567.0);
+ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1234567",
+ "%.10g", 1234567.0);
+#if TRIO_C99
+ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "0x2.ap+4",
+ "%a", 42.0);
+ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "0x1.2d687p+20",
+ "%a", 1234567.0);
+ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "0X1.2D687P+20",
+ "%A", 1234567.0);
+#endif
+ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.79769e+308",
+ "%g", 1.79769e+308);
+ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "nan",
+ "%f", trio_nan());
+ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "NAN",
+ "%F", trio_nan());
+ nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "-inf",
+ "%f", trio_ninf());
+
+ return nerrors;
+}
+
+/*************************************************************************
+ *
+ */
+int
+VerifyScanningOneString
+TRIO_ARGS5((file, line, expected, format, original),
+ TRIO_CONST char *file,
+ int line,
+ TRIO_CONST char *expected,
+ TRIO_CONST char *format,
+ char *original)
+{
+ char string[512];
+ char data[512];
+
+ trio_snprintf(data, sizeof(data), "%s", original);
+ trio_sscanf(data, format, string);
+ return Verify(file, line, expected, "%s", string);
+}
+
+int
+VerifyScanningStrings(TRIO_NOARGS)
+{
+ int nerrors = 0;
+
+ nerrors += VerifyScanningOneString(__FILE__, __LINE__, "hello",
+ "%s", "hello");
+ nerrors += VerifyScanningOneString(__FILE__, __LINE__, "hello",
+ "%s", "hello world");
+ nerrors += VerifyScanningOneString(__FILE__, __LINE__, "hello world",
+ "%[^\n]", "hello world");
+ nerrors += VerifyScanningOneString(__FILE__, __LINE__, "(nil)",
+ "%s", NULL);
+ nerrors += VerifyScanningOneString(__FILE__, __LINE__, "hello",
+ "%20s", "hello");
+ nerrors += VerifyScanningOneString(__FILE__, __LINE__, "he",
+ "%2s", "hello");
+ nerrors += VerifyScanningOneString(__FILE__, __LINE__, "ab",
+ "%[ab]", "abcba");
+ nerrors += VerifyScanningOneString(__FILE__, __LINE__, "abcba",
+ "%[abc]", "abcba");
+ nerrors += VerifyScanningOneString(__FILE__, __LINE__, "abcba",
+ "%[a-c]", "abcba");
+#if TRIO_EXTENSION
+ nerrors += VerifyScanningOneString(__FILE__, __LINE__, "abcba",
+ "%[[:alpha:]]", "abcba");
+#endif
+ nerrors += VerifyScanningOneString(__FILE__, __LINE__, "ba",
+ "%*[ab]c%[^\n]", "abcba");
+
+ return nerrors;
+}
+
+/*************************************************************************
+ *
+ */
+int
+VerifyScanningRegression(TRIO_NOARGS)
+{
+ int nerrors = 0;
+ int rc;
+ int index;
+ double dnumber;
+ trio_long_double_t ldnumber;
+ long lnumber;
+ int number;
+ char ch;
+
+ rc = trio_sscanf("1.5", "%lf%n", &dnumber, &index);
+ nerrors += Verify(__FILE__, __LINE__, "1 3 1.500000",
+ "%d %d %f", rc, index, dnumber);
+ rc = trio_sscanf("q 123", "%c%ld", &ch, &lnumber);
+ nerrors += Verify(__FILE__, __LINE__, "q 123",
+ "%c %ld", ch, lnumber);
+ rc = trio_sscanf("abc", "%*s%n", &number);
+ nerrors += Verify(__FILE__, __LINE__, "0 3",
+ "%d %d", rc, number);
+ rc = trio_sscanf("abc def", "%*s%n", &number);
+ nerrors += Verify(__FILE__, __LINE__, "0 3",
+ "%d %d", rc, number);
+ rc = trio_sscanf("0.141882295971771490", "%lf", &dnumber);
+ number = 33;
+ rc = trio_sscanf("total 1", "total %d", &number);
+ nerrors += Verify(__FILE__, __LINE__, "1 1",
+ "%d %d", rc, number);
+#if defined(TRIO_BREESE)
+ nerrors += Verify(__FILE__, __LINE__, "1 0.141882295971771488",
+ "%d %.18f", rc, dnumber);
+ rc = trio_sscanf("0.141882295971771490", "%Lf", &ldnumber);
+ nerrors += Verify(__FILE__, __LINE__, "1 0.141882295971771490",
+ "%d %.18Lf", rc, ldnumber);
+#endif
+ return nerrors;
+}
+
+/*************************************************************************
+ *
+ */
+int
+VerifyScanning(TRIO_NOARGS)
+{
+ int nerrors = 0;
+
+ nerrors += VerifyScanningIntegers();
+ nerrors += VerifyScanningFloats();
+ nerrors += VerifyScanningStrings();
+ nerrors += VerifyScanningRegression();
+
+ return nerrors;
+}
+
+/*************************************************************************
+ *
+ */
+int
+VerifyStrings(TRIO_NOARGS)
+{
+ int nerrors = 0;
+#if !defined(TRIO_MINIMAL)
+ char buffer[512];
+ double dnumber;
+ float fnumber;
+ char *end;
+
+ /* Comparison */
+ trio_copy(buffer, "Find me now");
+ if (trio_length(buffer) != sizeof("Find me now") - 1) {
+ nerrors++;
+ Report0(__FILE__, __LINE__);
+ }
+ if (!trio_equal(buffer, "Find me now")) {
+ nerrors++;
+ Report0(__FILE__, __LINE__);
+ }
+ if (!trio_equal_case(buffer, "Find me now")) {
+ nerrors++;
+ Report0(__FILE__, __LINE__);
+ }
+ if (trio_equal_case(buffer, "FIND ME NOW")) {
+ nerrors++;
+ Report0(__FILE__, __LINE__);
+ }
+ if (!trio_equal_max(buffer, sizeof("Find me") - 1, "Find ME")) {
+ nerrors++;
+ Report0(__FILE__, __LINE__);
+ }
+ if (!trio_contains(buffer, "me")) {
+ nerrors++;
+ Report0(__FILE__, __LINE__);
+ }
+ if (trio_contains(buffer, "and me")) {
+ nerrors++;
+ Report0(__FILE__, __LINE__);
+ }
+ if (trio_substring(buffer, "me") == NULL) {
+ nerrors++;
+ Report0(__FILE__, __LINE__);
+ }
+ if (trio_substring_max(buffer, 4, "me") != NULL) {
+ nerrors++;
+ Report0(__FILE__, __LINE__);
+ }
+ if (!trio_match(buffer, "* me *")) {
+ nerrors++;
+ Report0(__FILE__, __LINE__);
+ }
+ if (trio_match_case(buffer, "* ME *")) {
+ nerrors++;
+ Report0(__FILE__, __LINE__);
+ }
+ if (trio_index(buffer, 'n') == NULL) {
+ nerrors++;
+ Report0(__FILE__, __LINE__);
+ }
+ if (trio_index(buffer, '_') != NULL) {
+ nerrors++;
+ Report0(__FILE__, __LINE__);
+ }
+ if (trio_index_last(buffer, 'n') == NULL) {
+ nerrors++;
+ Report0(__FILE__, __LINE__);
+ }
+
+ /* Append */
+ trio_copy(buffer, "Find me now");
+ if (!trio_append(buffer, " and again")) {
+ nerrors++;
+ Report0(__FILE__, __LINE__);
+ }
+ if (!trio_equal(buffer, "Find me now and again")) {
+ nerrors++;
+ Report0(__FILE__, __LINE__);
+ }
+ if (!trio_append_max(buffer, 0, "should not appear")) {
+ nerrors++;
+ Report0(__FILE__, __LINE__);
+ }
+ if (!trio_equal(buffer, "Find me now and again")) {
+ nerrors++;
+ Report0(__FILE__, __LINE__);
+ }
+
+ /* To upper/lower */
+ trio_copy(buffer, "Find me now");
+ trio_upper(buffer);
+ if (!trio_equal_case(buffer, "FIND ME NOW")) {
+ nerrors++;
+ Report0(__FILE__, __LINE__);
+ }
+ trio_lower(buffer);
+ if (!trio_equal_case(buffer, "find me now")) {
+ nerrors++;
+ Report0(__FILE__, __LINE__);
+ }
+
+ /* Double conversion */
+ trio_copy(buffer, "3.1415");
+ dnumber = trio_to_double(buffer, NULL);
+ if (!DOUBLE_EQUAL(dnumber, 3.1415)) {
+ nerrors++;
+ Report0(__FILE__, __LINE__);
+ }
+ fnumber = trio_to_float(buffer, NULL);
+ if (!FLOAT_EQUAL(fnumber, 3.1415)) {
+ nerrors++;
+ Report0(__FILE__, __LINE__);
+ }
+
+ /* Long conversion */
+ trio_copy(buffer, "3.1415");
+ if (trio_to_long(buffer, NULL, 10) != 3L) {
+ nerrors++;
+ Report0(__FILE__, __LINE__);
+ }
+ if (trio_to_long(buffer, NULL, 4) != 3L) {
+ nerrors++;
+ Report0(__FILE__, __LINE__);
+ }
+ trio_to_long(buffer, &end, 2);
+ if (end != buffer) {
+ nerrors++;
+ Report0(__FILE__, __LINE__);
+ }
+
+#endif /* !defined(TRIO_MINIMAL) */
+ return nerrors;
+}
+
+/*************************************************************************
+ *
+ */
+int
+VerifyDynamicStrings(TRIO_NOARGS)
+{
+ int nerrors = 0;
+#if !defined(TRIO_MINIMAL)
+ trio_string_t *string;
+
+ string = trio_xstring_duplicate("Find me now");
+ if (string == NULL) {
+ nerrors++;
+ goto error;
+ }
+ if (!trio_xstring_equal(string, "FIND ME NOW"))
+ nerrors++;
+ if (!trio_xstring_append(string, " and again") ||
+ !trio_xstring_equal(string, "FIND ME NOW AND AGAIN"))
+ nerrors++;
+ if (!trio_xstring_contains(string, "me"))
+ nerrors++;
+ if (trio_xstring_contains(string, "ME"))
+ nerrors++;
+ if (!trio_xstring_match(string, "* me *"))
+ nerrors++;
+ if (trio_xstring_match_case(string, "* ME *"))
+ nerrors++;
+
+ error:
+ if (string)
+ trio_string_destroy(string);
+
+#endif /* !defined(TRIO_MINIMAL) */
+ return nerrors;
+}
+
+/*************************************************************************
+ *
+ */
+int
+VerifyNaN(TRIO_NOARGS)
+{
+ double ninf_number = trio_ninf();
+ double pinf_number = trio_pinf();
+ double nan_number = trio_nan();
+ int nerrors = 0;
+
+ nerrors += Verify(__FILE__, __LINE__, "-1",
+ "%d", trio_isinf(ninf_number));
+ nerrors += Verify(__FILE__, __LINE__, "0",
+ "%d", trio_isinf(42.0));
+ nerrors += Verify(__FILE__, __LINE__, "1",
+ "%d", trio_isinf(pinf_number));
+ nerrors += Verify(__FILE__, __LINE__, "1",
+ "%d", trio_isnan(nan_number));
+ nerrors += Verify(__FILE__, __LINE__, "0",
+ "%d", trio_isnan(42.0));
+
+ return nerrors;
+}
+
+/*************************************************************************
+ *
+ */
+int
+main(TRIO_NOARGS)
+{
+ int nerrors = 0;
+
+ printf("%s\n", rcsid);
+
+ /* Override system locale settings */
+ trio_locale_set_decimal_point(".");
+ trio_locale_set_thousand_separator(",");
+ trio_locale_set_grouping("\3");
+
+ printf("Verifying strings\n");
+ nerrors += VerifyStrings();
+
+ printf("Verifying dynamic strings\n");
+ nerrors += VerifyDynamicStrings();
+
+ printf("Verifying special quantities\n");
+ nerrors += VerifyNaN();
+
+ printf("Verifying formatting\n");
+ nerrors += VerifyFormatting();
+
+ printf("Verifying scanning\n");
+ nerrors += VerifyScanning();
+
+ printf("Verifying return values\n");
+ nerrors += VerifyErrors();
+ nerrors += VerifyReturnValues();
+
+ printf("Verifying allocation\n");
+ nerrors += VerifyAllocate();
+
+ if (nerrors == 0)
+ printf("Regression test suceeded\n");
+ else
+ printf("Regression test failed in %d instance(s)\n", nerrors);
+
+ return nerrors ? 1 : 0;
+}
diff --git a/trio/strio.h b/trio/strio.h
new file mode 100644
index 00000000..d90cfcfd
--- /dev/null
+++ b/trio/strio.h
@@ -0,0 +1,73 @@
+/*************************************************************************
+ *
+ * $Id: strio.h,v 1.11 2001/12/27 17:29:20 breese Exp $
+ *
+ * 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.
+ *
+ ************************************************************************
+ *
+ * This maintains backwards compatibility with the strio functions.
+ *
+ ************************************************************************/
+
+#ifndef TRIO_STRIO_H
+#define TRIO_STRIO_H
+
+#if !(defined(DEBUG) || defined(NDEBUG))
+# define NDEBUG
+#endif
+#include "triostr.h"
+
+enum {
+ STRIO_HASH_NONE = TRIO_HASH_NONE,
+ STRIO_HASH_PLAIN = TRIO_HASH_PLAIN,
+ STRIO_HASH_TWOSIGNED = TRIO_HASH_TWOSIGNED
+};
+
+#define StrAlloc(n) trio_create(n)
+#define StrAppend(x,y) ((void)trio_append((x),(y)),(x))
+#define StrAppendMax(x,n,y) ((void)trio_append_max((x),(n),(y)),(x))
+#define StrContains(x,y) trio_contains((x),(y))
+#define StrCopy(x,y) ((void)trio_copy((x),(y)),(x))
+#define StrCopyMax(x,n,y) ((void)trio_copy_max((x),(n),(y)),(x))
+#define StrDuplicate(x) trio_duplicate(x)
+#define StrDuplicateMax(x,n) trio_duplicate((x),(n))
+#define StrEqual(x,y) trio_equal((x),(y))
+#define StrEqualCase(x,y) trio_equal_case((x),(y))
+#define StrEqualCaseMax(x,n,y) trio_equal_case_max((x),(n),(y))
+#define StrEqualLocale(x,y) trio_equal_locale((x),(y))
+#define StrEqualMax(x,n,y) trio_equal_max((x),(n),(y))
+#define StrError(n) trio_error(n)
+#define StrFree(x) trio_destroy(x)
+#define StrFormat trio_sprintf
+#define StrFormatAlloc trio_aprintf
+#define StrFormatAppendMax trio_snprintfcat
+#define StrFormatDateMax(x,n,y,t) trio_format_date_max((x),(n),(y),(t))
+#define StrFormatMax trio_snprintf
+#define StrHash(x,n) trio_hash((x),(n))
+#define StrIndex(x,y) trio_index((x),(y))
+#define StrIndexLast(x,y) trio_index_last((x),(y))
+#define StrLength(x) trio_length((x))
+#define StrMatch(x,y) trio_match((x),(y))
+#define StrMatchCase(x,y) trio_match_case((x),(y))
+#define StrScan trio_sscanf
+#define StrSpanFunction(x,f) trio_span_function((x),(f))
+#define StrSubstring(x,y) trio_substring((x),(y))
+#define StrSubstringMax(x,n,y) trio_substring_max((x),(n),(y))
+#define StrToDouble(x,y) trio_to_double((x),(y))
+#define StrToFloat(x,y) trio_to_float((x),(y))
+#define StrTokenize(x,y) trio_tokenize((x),(y))
+#define StrToLong(x,y,n) trio_to_long((x),(y),(n))
+#define StrToUnsignedLong(x,y,n) trio_to_unsigned_long((x),(n),(y))
+#define StrToUpper(x) trio_upper(x)
+
+#endif /* TRIO_STRIO_H */
diff --git a/trio/trio.c b/trio/trio.c
new file mode 100644
index 00000000..8494e556
--- /dev/null
+++ b/trio/trio.c
@@ -0,0 +1,6855 @@
+/*************************************************************************
+ *
+ * $Id: trio.c,v 1.75 2003/03/01 15:34:01 breese Exp $
+ *
+ * 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.
+ *
+ *************************************************************************
+ *
+ * A note to trio contributors:
+ *
+ * Avoid heap allocation at all costs to ensure that the trio functions
+ * are async-safe. The exceptions are the printf/fprintf functions, which
+ * uses fputc, and the asprintf functions and the <alloc> modifier, which
+ * by design are required to allocate form the heap.
+ *
+ ************************************************************************/
+
+/*
+ * TODO:
+ * - Scan is probably too permissive about its modifiers.
+ * - C escapes in %#[] ?
+ * - Multibyte characters (done for format parsing, except scan groups)
+ * - Complex numbers? (C99 _Complex)
+ * - Boolean values? (C99 _Bool)
+ * - C99 NaN(n-char-sequence) missing. The n-char-sequence can be used
+ * to print the mantissa, e.g. NaN(0xc000000000000000)
+ * - Should we support the GNU %a alloc modifier? GNU has an ugly hack
+ * for %a, because C99 used %a for other purposes. If specified as
+ * %as or %a[ it is interpreted as the alloc modifier, otherwise as
+ * the C99 hex-float. This means that you cannot scan %as as a hex-float
+ * immediately followed by an 's'.
+ * - Scanning of collating symbols.
+ */
+
+/*************************************************************************
+ * Trio include files
+ */
+#include "triodef.h"
+#include "trio.h"
+#include "triop.h"
+#include "trionan.h"
+#if !defined(TRIO_MINIMAL)
+# include "triostr.h"
+#endif
+
+/**************************************************************************
+ *
+ * Definitions
+ *
+ *************************************************************************/
+
+#include <math.h>
+#include <limits.h>
+#include <float.h>
+
+#if defined(__STDC_ISO_10646__) || defined(MB_LEN_MAX) || defined(USE_MULTIBYTE) || TRIO_WIDECHAR
+# define TRIO_COMPILER_SUPPORTS_MULTIBYTE
+# if !defined(MB_LEN_MAX)
+# define MB_LEN_MAX 6
+# endif
+#endif
+
+#if (defined(TRIO_COMPILER_MSVC) && (_MSC_VER >= 1100)) || defined(TRIO_COMPILER_BCB)
+# define TRIO_COMPILER_SUPPORTS_MSVC_INT
+#endif
+
+/*************************************************************************
+ * Generic definitions
+ */
+
+#if !(defined(DEBUG) || defined(NDEBUG))
+# define NDEBUG
+#endif
+
+#include <assert.h>
+#include <ctype.h>
+#if !defined(TRIO_COMPILER_SUPPORTS_C99)
+# define isblank(x) (((x)==32) || ((x)==9))
+#endif
+#if defined(TRIO_COMPILER_ANCIENT)
+# include <varargs.h>
+#else
+# include <stdarg.h>
+#endif
+#include <stddef.h>
+#include <errno.h>
+
+#ifndef NULL
+# define NULL 0
+#endif
+#define NIL ((char)0)
+#ifndef FALSE
+# define FALSE (1 == 0)
+# define TRUE (! FALSE)
+#endif
+#define BOOLEAN_T int
+
+/* mincore() can be used for debugging purposes */
+#define VALID(x) (NULL != (x))
+
+#if TRIO_ERRORS
+ /*
+ * Encode the error code and the position. This is decoded
+ * with TRIO_ERROR_CODE and TRIO_ERROR_POSITION.
+ */
+# define TRIO_ERROR_RETURN(x,y) (- ((x) + ((y) << 8)))
+#else
+# define TRIO_ERROR_RETURN(x,y) (-1)
+#endif
+
+typedef unsigned long trio_flags_t;
+
+
+/*************************************************************************
+ * Platform specific definitions
+ */
+#if defined(TRIO_PLATFORM_UNIX)
+# include <unistd.h>
+# include <signal.h>
+# include <locale.h>
+# define USE_LOCALE
+#endif /* TRIO_PLATFORM_UNIX */
+#if defined(TRIO_PLATFORM_VMS)
+# include <unistd.h>
+#endif
+#if defined(TRIO_PLATFORM_WIN32)
+# include <io.h>
+# define read _read
+# define write _write
+#endif /* TRIO_PLATFORM_WIN32 */
+
+#if TRIO_WIDECHAR
+# if defined(TRIO_COMPILER_SUPPORTS_ISO94)
+# include <wchar.h>
+# include <wctype.h>
+typedef wchar_t trio_wchar_t;
+typedef wint_t trio_wint_t;
+# else
+typedef char trio_wchar_t;
+typedef int trio_wint_t;
+# define WCONST(x) L ## x
+# define WEOF EOF
+# define iswalnum(x) isalnum(x)
+# define iswalpha(x) isalpha(x)
+# define iswblank(x) isblank(x)
+# define iswcntrl(x) iscntrl(x)
+# define iswdigit(x) isdigit(x)
+# define iswgraph(x) isgraph(x)
+# define iswlower(x) islower(x)
+# define iswprint(x) isprint(x)
+# define iswpunct(x) ispunct(x)
+# define iswspace(x) isspace(x)
+# define iswupper(x) isupper(x)
+# define iswxdigit(x) isxdigit(x)
+# endif
+#endif
+
+
+/*************************************************************************
+ * Compiler dependent definitions
+ */
+
+/* Support for long long */
+#ifndef __cplusplus
+# if !defined(USE_LONGLONG)
+# if defined(TRIO_COMPILER_GCC) && !defined(__STRICT_ANSI__)
+# define USE_LONGLONG
+# elif defined(TRIO_COMPILER_SUNPRO)
+# define USE_LONGLONG
+# elif defined(_LONG_LONG) || defined(_LONGLONG)
+# define USE_LONGLONG
+# endif
+# endif
+#endif
+
+/* The extra long numbers */
+#if defined(USE_LONGLONG)
+typedef signed long long int trio_longlong_t;
+typedef unsigned long long int trio_ulonglong_t;
+#elif defined(TRIO_COMPILER_SUPPORTS_MSVC_INT)
+typedef signed __int64 trio_longlong_t;
+typedef unsigned __int64 trio_ulonglong_t;
+#else
+typedef TRIO_SIGNED long int trio_longlong_t;
+typedef unsigned long int trio_ulonglong_t;
+#endif
+
+/* Maximal and fixed integer types */
+#if defined(TRIO_COMPILER_SUPPORTS_C99)
+# include <stdint.h>
+typedef intmax_t trio_intmax_t;
+typedef uintmax_t trio_uintmax_t;
+typedef int8_t trio_int8_t;
+typedef int16_t trio_int16_t;
+typedef int32_t trio_int32_t;
+typedef int64_t trio_int64_t;
+#elif defined(TRIO_COMPILER_SUPPORTS_UNIX98)
+# include <inttypes.h>
+typedef intmax_t trio_intmax_t;
+typedef uintmax_t trio_uintmax_t;
+typedef int8_t trio_int8_t;
+typedef int16_t trio_int16_t;
+typedef int32_t trio_int32_t;
+typedef int64_t trio_int64_t;
+#elif defined(TRIO_COMPILER_SUPPORTS_MSVC_INT)
+typedef trio_longlong_t trio_intmax_t;
+typedef trio_ulonglong_t trio_uintmax_t;
+typedef __int8 trio_int8_t;
+typedef __int16 trio_int16_t;
+typedef __int32 trio_int32_t;
+typedef __int64 trio_int64_t;
+#else
+typedef trio_longlong_t trio_intmax_t;
+typedef trio_ulonglong_t trio_uintmax_t;
+# if defined(TRIO_INT8_T)
+typedef TRIO_INT8_T trio_int8_t;
+# else
+typedef TRIO_SIGNED char trio_int8_t;
+# endif
+# if defined(TRIO_INT16_T)
+typedef TRIO_INT16_T trio_int16_t;
+# else
+typedef TRIO_SIGNED short trio_int16_t;
+# endif
+# if defined(TRIO_INT32_T)
+typedef TRIO_INT32_T trio_int32_t;
+# else
+typedef TRIO_SIGNED int trio_int32_t;
+# endif
+# if defined(TRIO_INT64_T)
+typedef TRIO_INT64_T trio_int64_t;
+# else
+typedef trio_longlong_t trio_int64_t;
+# endif
+#endif
+
+#if !(defined(TRIO_COMPILER_SUPPORTS_C99) \
+ || defined(TRIO_COMPILER_SUPPORTS_UNIX01))
+# define floorl(x) floor((double)(x))
+# define fmodl(x,y) fmod((double)(x),(double)(y))
+# define powl(x,y) pow((double)(x),(double)(y))
+#endif
+
+#define TRIO_FABS(x) (((x) < 0.0) ? -(x) : (x))
+
+/*************************************************************************
+ * Internal Definitions
+ */
+
+#ifndef DECIMAL_DIG
+# define DECIMAL_DIG DBL_DIG
+#endif
+
+/* Long double sizes */
+#ifdef LDBL_DIG
+# define MAX_MANTISSA_DIGITS LDBL_DIG
+# define MAX_EXPONENT_DIGITS 4
+# define MAX_DOUBLE_DIGITS LDBL_MAX_10_EXP
+#else
+# define MAX_MANTISSA_DIGITS DECIMAL_DIG
+# define MAX_EXPONENT_DIGITS 3
+# define MAX_DOUBLE_DIGITS DBL_MAX_10_EXP
+#endif
+
+#if defined(TRIO_COMPILER_ANCIENT) || !defined(LDBL_DIG)
+# undef LDBL_DIG
+# undef LDBL_MANT_DIG
+# undef LDBL_EPSILON
+# define LDBL_DIG DBL_DIG
+# define LDBL_MANT_DIG DBL_MANT_DIG
+# define LDBL_EPSILON DBL_EPSILON
+#endif
+
+/* The maximal number of digits is for base 2 */
+#define MAX_CHARS_IN(x) (sizeof(x) * CHAR_BIT)
+/* The width of a pointer. The number of bits in a hex digit is 4 */
+#define POINTER_WIDTH ((sizeof("0x") - 1) + sizeof(trio_pointer_t) * CHAR_BIT / 4)
+
+/* Infinite and Not-A-Number for floating-point */
+#define INFINITE_LOWER "inf"
+#define INFINITE_UPPER "INF"
+#define LONG_INFINITE_LOWER "infinite"
+#define LONG_INFINITE_UPPER "INFINITE"
+#define NAN_LOWER "nan"
+#define NAN_UPPER "NAN"
+
+/* Various constants */
+enum {
+ TYPE_PRINT = 1,
+ TYPE_SCAN = 2,
+
+ /* Flags. FLAGS_LAST must be less than ULONG_MAX */
+ FLAGS_NEW = 0,
+ FLAGS_STICKY = 1,
+ FLAGS_SPACE = 2 * FLAGS_STICKY,
+ FLAGS_SHOWSIGN = 2 * FLAGS_SPACE,
+ FLAGS_LEFTADJUST = 2 * FLAGS_SHOWSIGN,
+ FLAGS_ALTERNATIVE = 2 * FLAGS_LEFTADJUST,
+ FLAGS_SHORT = 2 * FLAGS_ALTERNATIVE,
+ FLAGS_SHORTSHORT = 2 * FLAGS_SHORT,
+ FLAGS_LONG = 2 * FLAGS_SHORTSHORT,
+ FLAGS_QUAD = 2 * FLAGS_LONG,
+ FLAGS_LONGDOUBLE = 2 * FLAGS_QUAD,
+ FLAGS_SIZE_T = 2 * FLAGS_LONGDOUBLE,
+ FLAGS_PTRDIFF_T = 2 * FLAGS_SIZE_T,
+ FLAGS_INTMAX_T = 2 * FLAGS_PTRDIFF_T,
+ FLAGS_NILPADDING = 2 * FLAGS_INTMAX_T,
+ FLAGS_UNSIGNED = 2 * FLAGS_NILPADDING,
+ FLAGS_UPPER = 2 * FLAGS_UNSIGNED,
+ FLAGS_WIDTH = 2 * FLAGS_UPPER,
+ FLAGS_WIDTH_PARAMETER = 2 * FLAGS_WIDTH,
+ FLAGS_PRECISION = 2 * FLAGS_WIDTH_PARAMETER,
+ FLAGS_PRECISION_PARAMETER = 2 * FLAGS_PRECISION,
+ FLAGS_BASE = 2 * FLAGS_PRECISION_PARAMETER,
+ FLAGS_BASE_PARAMETER = 2 * FLAGS_BASE,
+ FLAGS_FLOAT_E = 2 * FLAGS_BASE_PARAMETER,
+ FLAGS_FLOAT_G = 2 * FLAGS_FLOAT_E,
+ FLAGS_QUOTE = 2 * FLAGS_FLOAT_G,
+ FLAGS_WIDECHAR = 2 * FLAGS_QUOTE,
+ FLAGS_ALLOC = 2 * FLAGS_WIDECHAR,
+ FLAGS_IGNORE = 2 * FLAGS_ALLOC,
+ FLAGS_IGNORE_PARAMETER = 2 * FLAGS_IGNORE,
+ FLAGS_VARSIZE_PARAMETER = 2 * FLAGS_IGNORE_PARAMETER,
+ FLAGS_FIXED_SIZE = 2 * FLAGS_VARSIZE_PARAMETER,
+ FLAGS_LAST = FLAGS_FIXED_SIZE,
+ /* Reused flags */
+ FLAGS_EXCLUDE = FLAGS_SHORT,
+ FLAGS_USER_DEFINED = FLAGS_IGNORE,
+ FLAGS_ROUNDING = FLAGS_INTMAX_T,
+ /* Compounded flags */
+ FLAGS_ALL_VARSIZES = FLAGS_LONG | FLAGS_QUAD | FLAGS_INTMAX_T | FLAGS_PTRDIFF_T | FLAGS_SIZE_T,
+ FLAGS_ALL_SIZES = FLAGS_ALL_VARSIZES | FLAGS_SHORTSHORT | FLAGS_SHORT,
+
+ NO_POSITION = -1,
+ NO_WIDTH = 0,
+ NO_PRECISION = -1,
+ NO_SIZE = -1,
+
+ /* Do not change these */
+ NO_BASE = -1,
+ MIN_BASE = 2,
+ MAX_BASE = 36,
+ BASE_BINARY = 2,
+ BASE_OCTAL = 8,
+ BASE_DECIMAL = 10,
+ BASE_HEX = 16,
+
+ /* Maximal number of allowed parameters */
+ MAX_PARAMETERS = 64,
+ /* Maximal number of characters in class */
+ MAX_CHARACTER_CLASS = UCHAR_MAX + 1,
+
+ /* Maximal string lengths for user-defined specifiers */
+ MAX_USER_NAME = 64,
+ MAX_USER_DATA = 256,
+
+ /* Maximal length of locale separator strings */
+ MAX_LOCALE_SEPARATOR_LENGTH = MB_LEN_MAX,
+ /* Maximal number of integers in grouping */
+ MAX_LOCALE_GROUPS = 64,
+
+ /* Initial size of asprintf buffer */
+ DYNAMIC_START_SIZE = 32
+};
+
+#define NO_GROUPING ((int)CHAR_MAX)
+
+/* Fundamental formatting parameter types */
+#define FORMAT_UNKNOWN 0
+#define FORMAT_INT 1
+#define FORMAT_DOUBLE 2
+#define FORMAT_CHAR 3
+#define FORMAT_STRING 4
+#define FORMAT_POINTER 5
+#define FORMAT_COUNT 6
+#define FORMAT_PARAMETER 7
+#define FORMAT_GROUP 8
+#if TRIO_GNU
+# define FORMAT_ERRNO 9
+#endif
+#if TRIO_EXTENSION
+# define FORMAT_USER_DEFINED 10
+#endif
+
+/* Character constants */
+#define CHAR_IDENTIFIER '%'
+#define CHAR_BACKSLASH '\\'
+#define CHAR_QUOTE '\"'
+#define CHAR_ADJUST ' '
+
+/* Character class expressions */
+#define CLASS_ALNUM "[:alnum:]"
+#define CLASS_ALPHA "[:alpha:]"
+#define CLASS_BLANK "[:blank:]"
+#define CLASS_CNTRL "[:cntrl:]"
+#define CLASS_DIGIT "[:digit:]"
+#define CLASS_GRAPH "[:graph:]"
+#define CLASS_LOWER "[:lower:]"
+#define CLASS_PRINT "[:print:]"
+#define CLASS_PUNCT "[:punct:]"
+#define CLASS_SPACE "[:space:]"
+#define CLASS_UPPER "[:upper:]"
+#define CLASS_XDIGIT "[:xdigit:]"
+
+/*
+ * SPECIFIERS:
+ *
+ *
+ * a Hex-float
+ * A Hex-float
+ * c Character
+ * C Widechar character (wint_t)
+ * d Decimal
+ * e Float
+ * E Float
+ * F Float
+ * F Float
+ * g Float
+ * G Float
+ * i Integer
+ * m Error message
+ * n Count
+ * o Octal
+ * p Pointer
+ * s String
+ * S Widechar string (wchar_t *)
+ * u Unsigned
+ * x Hex
+ * X Hex
+ * [] Group
+ * <> User-defined
+ *
+ * Reserved:
+ *
+ * D Binary Coded Decimal %D(length,precision) (OS/390)
+ */
+#define SPECIFIER_CHAR 'c'
+#define SPECIFIER_STRING 's'
+#define SPECIFIER_DECIMAL 'd'
+#define SPECIFIER_INTEGER 'i'
+#define SPECIFIER_UNSIGNED 'u'
+#define SPECIFIER_OCTAL 'o'
+#define SPECIFIER_HEX 'x'
+#define SPECIFIER_HEX_UPPER 'X'
+#define SPECIFIER_FLOAT_E 'e'
+#define SPECIFIER_FLOAT_E_UPPER 'E'
+#define SPECIFIER_FLOAT_F 'f'
+#define SPECIFIER_FLOAT_F_UPPER 'F'
+#define SPECIFIER_FLOAT_G 'g'
+#define SPECIFIER_FLOAT_G_UPPER 'G'
+#define SPECIFIER_POINTER 'p'
+#define SPECIFIER_GROUP '['
+#define SPECIFIER_UNGROUP ']'
+#define SPECIFIER_COUNT 'n'
+#if TRIO_UNIX98
+# define SPECIFIER_CHAR_UPPER 'C'
+# define SPECIFIER_STRING_UPPER 'S'
+#endif
+#if TRIO_C99
+# define SPECIFIER_HEXFLOAT 'a'
+# define SPECIFIER_HEXFLOAT_UPPER 'A'
+#endif
+#if TRIO_GNU
+# define SPECIFIER_ERRNO 'm'
+#endif
+#if TRIO_EXTENSION
+# define SPECIFIER_BINARY 'b'
+# define SPECIFIER_BINARY_UPPER 'B'
+# define SPECIFIER_USER_DEFINED_BEGIN '<'
+# define SPECIFIER_USER_DEFINED_END '>'
+# define SPECIFIER_USER_DEFINED_SEPARATOR ':'
+#endif
+
+/*
+ * QUALIFIERS:
+ *
+ *
+ * Numbers = d,i,o,u,x,X
+ * Float = a,A,e,E,f,F,g,G
+ * String = s
+ * Char = c
+ *
+ *
+ * 9$ Position
+ * Use the 9th parameter. 9 can be any number between 1 and
+ * the maximal argument
+ *
+ * 9 Width
+ * Set width to 9. 9 can be any number, but must not be postfixed
+ * by '$'
+ *
+ * h Short
+ * Numbers:
+ * (unsigned) short int
+ *
+ * hh Short short
+ * Numbers:
+ * (unsigned) char
+ *
+ * l Long
+ * Numbers:
+ * (unsigned) long int
+ * String:
+ * as the S specifier
+ * Char:
+ * as the C specifier
+ *
+ * ll Long Long
+ * Numbers:
+ * (unsigned) long long int
+ *
+ * L Long Double
+ * Float
+ * long double
+ *
+ * # Alternative
+ * Float:
+ * Decimal-point is always present
+ * String:
+ * non-printable characters are handled as \number
+ *
+ * Spacing
+ *
+ * + Sign
+ *
+ * - Alignment
+ *
+ * . Precision
+ *
+ * * Parameter
+ * print: use parameter
+ * scan: no parameter (ignore)
+ *
+ * q Quad
+ *
+ * Z size_t
+ *
+ * w Widechar
+ *
+ * ' Thousands/quote
+ * Numbers:
+ * Integer part grouped in thousands
+ * Binary numbers:
+ * Number grouped in nibbles (4 bits)
+ * String:
+ * Quoted string
+ *
+ * j intmax_t
+ * t prtdiff_t
+ * z size_t
+ *
+ * ! Sticky
+ * @ Parameter (for both print and scan)
+ *
+ * I n-bit Integer
+ * Numbers:
+ * The following options exists
+ * I8 = 8-bit integer
+ * I16 = 16-bit integer
+ * I32 = 32-bit integer
+ * I64 = 64-bit integer
+ */
+#define QUALIFIER_POSITION '$'
+#define QUALIFIER_SHORT 'h'
+#define QUALIFIER_LONG 'l'
+#define QUALIFIER_LONG_UPPER 'L'
+#define QUALIFIER_ALTERNATIVE '#'
+#define QUALIFIER_SPACE ' '
+#define QUALIFIER_PLUS '+'
+#define QUALIFIER_MINUS '-'
+#define QUALIFIER_DOT '.'
+#define QUALIFIER_STAR '*'
+#define QUALIFIER_CIRCUMFLEX '^' /* For scanlists */
+#if TRIO_C99
+# define QUALIFIER_SIZE_T 'z'
+# define QUALIFIER_PTRDIFF_T 't'
+# define QUALIFIER_INTMAX_T 'j'
+#endif
+#if TRIO_BSD || TRIO_GNU
+# define QUALIFIER_QUAD 'q'
+#endif
+#if TRIO_GNU
+# define QUALIFIER_SIZE_T_UPPER 'Z'
+#endif
+#if TRIO_MISC
+# define QUALIFIER_WIDECHAR 'w'
+#endif
+#if TRIO_MICROSOFT
+# define QUALIFIER_FIXED_SIZE 'I'
+#endif
+#if TRIO_EXTENSION
+# define QUALIFIER_QUOTE '\''
+# define QUALIFIER_STICKY '!'
+# define QUALIFIER_VARSIZE '&' /* This should remain undocumented */
+# define QUALIFIER_PARAM '@' /* Experimental */
+# define QUALIFIER_COLON ':' /* For scanlists */
+# define QUALIFIER_EQUAL '=' /* For scanlists */
+# define QUALIFIER_ROUNDING_UPPER 'R'
+#endif
+
+
+/*************************************************************************
+ *
+ * Internal Structures
+ *
+ *************************************************************************/
+
+/* Parameters */
+typedef struct {
+ /* An indication of which entry in the data union is used */
+ int type;
+ /* The flags */
+ trio_flags_t flags;
+ /* The width qualifier */
+ int width;
+ /* The precision qualifier */
+ int precision;
+ /* The base qualifier */
+ int base;
+ /* The size for the variable size qualifier */
+ int varsize;
+ /* The marker of the end of the specifier */
+ int indexAfterSpecifier;
+ /* The data from the argument list */
+ union {
+ char *string;
+#if TRIO_WIDECHAR
+ trio_wchar_t *wstring;
+#endif
+ trio_pointer_t pointer;
+ union {
+ trio_intmax_t as_signed;
+ trio_uintmax_t as_unsigned;
+ } number;
+ double doubleNumber;
+ double *doublePointer;
+ trio_long_double_t longdoubleNumber;
+ trio_long_double_t *longdoublePointer;
+ int errorNumber;
+ } data;
+ /* For the user-defined specifier */
+ char user_name[MAX_USER_NAME];
+ char user_data[MAX_USER_DATA];
+} trio_parameter_t;
+
+/* Container for customized functions */
+typedef struct {
+ union {
+ trio_outstream_t out;
+ trio_instream_t in;
+ } stream;
+ trio_pointer_t closure;
+} trio_custom_t;
+
+/* General trio "class" */
+typedef struct _trio_class_t {
+ /*
+ * The function to write characters to a stream.
+ */
+ void (*OutStream) TRIO_PROTO((struct _trio_class_t *, int));
+ /*
+ * The function to read characters from a stream.
+ */
+ void (*InStream) TRIO_PROTO((struct _trio_class_t *, int *));
+ /*
+ * The current location in the stream.
+ */
+ trio_pointer_t location;
+ /*
+ * The character currently being processed.
+ */
+ int current;
+ /*
+ * The number of characters that would have been written/read
+ * if there had been sufficient space.
+ */
+ int processed;
+ /*
+ * The number of characters that are actually written/read.
+ * Processed and committed will only differ for the *nprintf
+ * and *nscanf functions.
+ */
+ int committed;
+ /*
+ * The upper limit of characters that may be written/read.
+ */
+ int max;
+ /*
+ * The last output error that was detected.
+ */
+ int error;
+} trio_class_t;
+
+/* References (for user-defined callbacks) */
+typedef struct _trio_reference_t {
+ trio_class_t *data;
+ trio_parameter_t *parameter;
+} trio_reference_t;
+
+/* Registered entries (for user-defined callbacks) */
+typedef struct _trio_userdef_t {
+ struct _trio_userdef_t *next;
+ trio_callback_t callback;
+ char *name;
+} trio_userdef_t;
+
+/*************************************************************************
+ *
+ * Internal Variables
+ *
+ *************************************************************************/
+
+static TRIO_CONST char rcsid[] = "@(#)$Id: trio.c,v 1.75 2003/03/01 15:34:01 breese Exp $";
+
+/*
+ * Need this to workaround a parser bug in HP C/iX compiler that fails
+ * to resolves macro definitions that includes type 'long double',
+ * e.g: va_arg(arg_ptr, long double)
+ */
+#if defined(TRIO_PLATFORM_MPEIX)
+static TRIO_CONST trio_long_double_t ___dummy_long_double = 0;
+#endif
+
+static TRIO_CONST char internalNullString[] = "(nil)";
+
+#if defined(USE_LOCALE)
+static struct lconv *internalLocaleValues = NULL;
+#endif
+
+/*
+ * UNIX98 says "in a locale where the radix character is not defined,
+ * the radix character defaults to a period (.)"
+ */
+static int internalDecimalPointLength = 1;
+static int internalThousandSeparatorLength = 1;
+static char internalDecimalPoint = '.';
+static char internalDecimalPointString[MAX_LOCALE_SEPARATOR_LENGTH + 1] = ".";
+static char internalThousandSeparator[MAX_LOCALE_SEPARATOR_LENGTH + 1] = ",";
+static char internalGrouping[MAX_LOCALE_GROUPS] = { (char)NO_GROUPING };
+
+static TRIO_CONST char internalDigitsLower[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+static TRIO_CONST char internalDigitsUpper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+static BOOLEAN_T internalDigitsUnconverted = TRUE;
+static int internalDigitArray[128];
+#if TRIO_EXTENSION
+static BOOLEAN_T internalCollationUnconverted = TRUE;
+static char internalCollationArray[MAX_CHARACTER_CLASS][MAX_CHARACTER_CLASS];
+#endif
+
+#if TRIO_EXTENSION
+static TRIO_VOLATILE trio_callback_t internalEnterCriticalRegion = NULL;
+static TRIO_VOLATILE trio_callback_t internalLeaveCriticalRegion = NULL;
+static trio_userdef_t *internalUserDef = NULL;
+#endif
+
+
+/*************************************************************************
+ *
+ * Internal Functions
+ *
+ ************************************************************************/
+
+#if defined(TRIO_MINIMAL)
+# define TRIO_STRING_PUBLIC static
+# include "triostr.c"
+#endif /* defined(TRIO_MINIMAL) */
+
+/*************************************************************************
+ * TrioIsQualifier
+ *
+ * Description:
+ * Remember to add all new qualifiers to this function.
+ * QUALIFIER_POSITION must not be added.
+ */
+TRIO_PRIVATE BOOLEAN_T
+TrioIsQualifier
+TRIO_ARGS1((character),
+ TRIO_CONST char character)
+{
+ /* QUALIFIER_POSITION is not included */
+ switch (character)
+ {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case QUALIFIER_PLUS:
+ case QUALIFIER_MINUS:
+ case QUALIFIER_SPACE:
+ case QUALIFIER_DOT:
+ case QUALIFIER_STAR:
+ case QUALIFIER_ALTERNATIVE:
+ case QUALIFIER_SHORT:
+ case QUALIFIER_LONG:
+ case QUALIFIER_LONG_UPPER:
+ case QUALIFIER_CIRCUMFLEX:
+#if defined(QUALIFIER_SIZE_T)
+ case QUALIFIER_SIZE_T:
+#endif
+#if defined(QUALIFIER_PTRDIFF_T)
+ case QUALIFIER_PTRDIFF_T:
+#endif
+#if defined(QUALIFIER_INTMAX_T)
+ case QUALIFIER_INTMAX_T:
+#endif
+#if defined(QUALIFIER_QUAD)
+ case QUALIFIER_QUAD:
+#endif
+#if defined(QUALIFIER_SIZE_T_UPPER)
+ case QUALIFIER_SIZE_T_UPPER:
+#endif
+#if defined(QUALIFIER_WIDECHAR)
+ case QUALIFIER_WIDECHAR:
+#endif
+#if defined(QUALIFIER_QUOTE)
+ case QUALIFIER_QUOTE:
+#endif
+#if defined(QUALIFIER_STICKY)
+ case QUALIFIER_STICKY:
+#endif
+#if defined(QUALIFIER_VARSIZE)
+ case QUALIFIER_VARSIZE:
+#endif
+#if defined(QUALIFIER_PARAM)
+ case QUALIFIER_PARAM:
+#endif
+#if defined(QUALIFIER_FIXED_SIZE)
+ case QUALIFIER_FIXED_SIZE:
+#endif
+#if defined(QUALIFIER_ROUNDING_UPPER)
+ case QUALIFIER_ROUNDING_UPPER:
+#endif
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+/*************************************************************************
+ * TrioSetLocale
+ */
+#if defined(USE_LOCALE)
+TRIO_PRIVATE void
+TrioSetLocale(TRIO_NOARGS)
+{
+ internalLocaleValues = (struct lconv *)localeconv();
+ if (internalLocaleValues)
+ {
+ if ((internalLocaleValues->decimal_point) &&
+ (internalLocaleValues->decimal_point[0] != NIL))
+ {
+ internalDecimalPointLength = trio_length(internalLocaleValues->decimal_point);
+ if (internalDecimalPointLength == 1)
+ {
+ internalDecimalPoint = internalLocaleValues->decimal_point[0];
+ }
+ else
+ {
+ internalDecimalPoint = NIL;
+ trio_copy_max(internalDecimalPointString,
+ sizeof(internalDecimalPointString),
+ internalLocaleValues->decimal_point);
+ }
+ }
+ if ((internalLocaleValues->thousands_sep) &&
+ (internalLocaleValues->thousands_sep[0] != NIL))
+ {
+ trio_copy_max(internalThousandSeparator,
+ sizeof(internalThousandSeparator),
+ internalLocaleValues->thousands_sep);
+ internalThousandSeparatorLength = trio_length(internalThousandSeparator);
+ }
+ if ((internalLocaleValues->grouping) &&
+ (internalLocaleValues->grouping[0] != NIL))
+ {
+ trio_copy_max(internalGrouping,
+ sizeof(internalGrouping),
+ internalLocaleValues->grouping);
+ }
+ }
+}
+#endif /* defined(USE_LOCALE) */
+
+TRIO_PRIVATE int
+TrioCalcThousandSeparatorLength
+TRIO_ARGS1((digits),
+ int digits)
+{
+#if TRIO_EXTENSION
+ int count = 0;
+ int step = NO_GROUPING;
+ char *groupingPointer = internalGrouping;
+
+ while (digits > 0)
+ {
+ if (*groupingPointer == CHAR_MAX)
+ {
+ /* Disable grouping */
+ break; /* while */
+ }
+ else if (*groupingPointer == 0)
+ {
+ /* Repeat last group */
+ if (step == NO_GROUPING)
+ {
+ /* Error in locale */
+ break; /* while */
+ }
+ }
+ else
+ {
+ step = *groupingPointer++;
+ }
+ if (digits > step)
+ count += internalThousandSeparatorLength;
+ digits -= step;
+ }
+ return count;
+#else
+ return 0;
+#endif
+}
+
+TRIO_PRIVATE BOOLEAN_T
+TrioFollowedBySeparator
+TRIO_ARGS1((position),
+ int position)
+{
+#if TRIO_EXTENSION
+ int step = 0;
+ char *groupingPointer = internalGrouping;
+
+ position--;
+ if (position == 0)
+ return FALSE;
+ while (position > 0)
+ {
+ if (*groupingPointer == CHAR_MAX)
+ {
+ /* Disable grouping */
+ break; /* while */
+ }
+ else if (*groupingPointer != 0)
+ {
+ step = *groupingPointer++;
+ }
+ if (step == 0)
+ break;
+ position -= step;
+ }
+ return (position == 0);
+#else
+ return FALSE;
+#endif
+}
+
+/*************************************************************************
+ * TrioGetPosition
+ *
+ * Get the %n$ position.
+ */
+TRIO_PRIVATE int
+TrioGetPosition
+TRIO_ARGS2((format, indexPointer),
+ TRIO_CONST char *format,
+ int *indexPointer)
+{
+#if TRIO_UNIX98
+ char *tmpformat;
+ int number = 0;
+ int index = *indexPointer;
+
+ number = (int)trio_to_long(&format[index], &tmpformat, BASE_DECIMAL);
+ index = (int)(tmpformat - format);
+ if ((number != 0) && (QUALIFIER_POSITION == format[index++]))
+ {
+ *indexPointer = index;
+ /*
+ * number is decreased by 1, because n$ starts from 1, whereas
+ * the array it is indexing starts from 0.
+ */
+ return number - 1;
+ }
+#endif
+ return NO_POSITION;
+}
+
+#if TRIO_EXTENSION
+/*************************************************************************
+ * TrioFindNamespace
+ *
+ * Find registered user-defined specifier.
+ * The prev argument is used for optimization only.
+ */
+TRIO_PRIVATE trio_userdef_t *
+TrioFindNamespace
+TRIO_ARGS2((name, prev),
+ TRIO_CONST char *name,
+ trio_userdef_t **prev)
+{
+ trio_userdef_t *def;
+
+ if (internalEnterCriticalRegion)
+ (void)internalEnterCriticalRegion(NULL);
+
+ for (def = internalUserDef; def; def = def->next)
+ {
+ /* Case-sensitive string comparison */
+ if (trio_equal_case(def->name, name))
+ break;
+
+ if (prev)
+ *prev = def;
+ }
+
+ if (internalLeaveCriticalRegion)
+ (void)internalLeaveCriticalRegion(NULL);
+
+ return def;
+}
+#endif
+
+/*************************************************************************
+ * TrioPower
+ *
+ * Description:
+ * Calculate pow(base, exponent), where number and exponent are integers.
+ */
+TRIO_PRIVATE trio_long_double_t
+TrioPower
+TRIO_ARGS2((number, exponent),
+ int number,
+ int exponent)
+{
+ trio_long_double_t result;
+
+ if (number == 10)
+ {
+ switch (exponent)
+ {
+ /* Speed up calculation of common cases */
+ case 0:
+ result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E-1);
+ break;
+ case 1:
+ result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+0);
+ break;
+ case 2:
+ result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+1);
+ break;
+ case 3:
+ result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+2);
+ break;
+ case 4:
+ result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+3);
+ break;
+ case 5:
+ result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+4);
+ break;
+ case 6:
+ result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+5);
+ break;
+ case 7:
+ result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+6);
+ break;
+ case 8:
+ result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+7);
+ break;
+ case 9:
+ result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+8);
+ break;
+ default:
+ result = powl((trio_long_double_t)number,
+ (trio_long_double_t)exponent);
+ break;
+ }
+ }
+ else
+ {
+ return powl((trio_long_double_t)number, (trio_long_double_t)exponent);
+ }
+ return result;
+}
+
+/*************************************************************************
+ * TrioLogarithm
+ */
+TRIO_PRIVATE double
+TrioLogarithm
+TRIO_ARGS2((number, base),
+ double number,
+ int base)
+{
+ double result;
+
+ if (number <= 0.0)
+ {
+ /* xlC crashes on log(0) */
+ result = (number == 0.0) ? trio_ninf() : trio_nan();
+ }
+ else
+ {
+ if (base == 10)
+ {
+ result = log10(number);
+ }
+ else
+ {
+ result = log10(number) / log10((double)base);
+ }
+ }
+ return result;
+}
+
+/*************************************************************************
+ * TrioLogarithmBase
+ */
+TRIO_PRIVATE double
+TrioLogarithmBase
+TRIO_ARGS1((base),
+ int base)
+{
+ switch (base)
+ {
+ case BASE_BINARY : return 1.0;
+ case BASE_OCTAL : return 3.0;
+ case BASE_DECIMAL: return 3.321928094887362345;
+ case BASE_HEX : return 4.0;
+ default : return TrioLogarithm((double)base, 2);
+ }
+}
+
+/*************************************************************************
+ * TrioParse
+ *
+ * Description:
+ * Parse the format string
+ */
+TRIO_PRIVATE int
+TrioParse
+TRIO_ARGS5((type, format, parameters, arglist, argarray),
+ int type,
+ TRIO_CONST char *format,
+ trio_parameter_t *parameters,
+ va_list *arglist,
+ trio_pointer_t *argarray)
+{
+ /* Count the number of times a parameter is referenced */
+ unsigned short usedEntries[MAX_PARAMETERS];
+ /* Parameter counters */
+ int parameterPosition;
+ int currentParam;
+ int maxParam = -1;
+ /* Utility variables */
+ trio_flags_t flags;
+ int width;
+ int precision;
+ int varsize;
+ int base;
+ int index; /* Index into formatting string */
+ int dots; /* Count number of dots in modifier part */
+ BOOLEAN_T positional; /* Does the specifier have a positional? */
+ BOOLEAN_T gotSticky = FALSE; /* Are there any sticky modifiers at all? */
+ /*
+ * indices specifies the order in which the parameters must be
+ * read from the va_args (this is necessary to handle positionals)
+ */
+ int indices[MAX_PARAMETERS];
+ int pos = 0;
+ /* Various variables */
+ char ch;
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
+ int charlen;
+#endif
+ int save_errno;
+ int i = -1;
+ int num;
+ char *tmpformat;
+
+ /* One and only one of arglist and argarray must be used */
+ assert((arglist != NULL) ^ (argarray != NULL));
+
+ /*
+ * The 'parameters' array is not initialized, but we need to
+ * know which entries we have used.
+ */
+ memset(usedEntries, 0, sizeof(usedEntries));
+
+ save_errno = errno;
+ index = 0;
+ parameterPosition = 0;
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
+ (void)mblen(NULL, 0);
+#endif
+
+ while (format[index])
+ {
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
+ if (! isascii(format[index]))
+ {
+ /*
+ * Multibyte characters cannot be legal specifiers or
+ * modifiers, so we skip over them.
+ */
+ charlen = mblen(&format[index], MB_LEN_MAX);
+ index += (charlen > 0) ? charlen : 1;
+ continue; /* while */
+ }
+#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
+ if (CHAR_IDENTIFIER == format[index++])
+ {
+ if (CHAR_IDENTIFIER == format[index])
+ {
+ index++;
+ continue; /* while */
+ }
+
+ flags = FLAGS_NEW;
+ dots = 0;
+ currentParam = TrioGetPosition(format, &index);
+ positional = (NO_POSITION != currentParam);
+ if (!positional)
+ {
+ /* We have no positional, get the next counter */
+ currentParam = parameterPosition;
+ }
+ if(currentParam >= MAX_PARAMETERS)
+ {
+ /* Bail out completely to make the error more obvious */
+ return TRIO_ERROR_RETURN(TRIO_ETOOMANY, index);
+ }
+
+ if (currentParam > maxParam)
+ maxParam = currentParam;
+
+ /* Default values */
+ width = NO_WIDTH;
+ precision = NO_PRECISION;
+ base = NO_BASE;
+ varsize = NO_SIZE;
+
+ while (TrioIsQualifier(format[index]))
+ {
+ ch = format[index++];
+
+ switch (ch)
+ {
+ case QUALIFIER_SPACE:
+ flags |= FLAGS_SPACE;
+ break;
+
+ case QUALIFIER_PLUS:
+ flags |= FLAGS_SHOWSIGN;
+ break;
+
+ case QUALIFIER_MINUS:
+ flags |= FLAGS_LEFTADJUST;
+ flags &= ~FLAGS_NILPADDING;
+ break;
+
+ case QUALIFIER_ALTERNATIVE:
+ flags |= FLAGS_ALTERNATIVE;
+ break;
+
+ case QUALIFIER_DOT:
+ if (dots == 0) /* Precision */
+ {
+ dots++;
+
+ /* Skip if no precision */
+ if (QUALIFIER_DOT == format[index])
+ break;
+
+ /* After the first dot we have the precision */
+ flags |= FLAGS_PRECISION;
+ if ((QUALIFIER_STAR == format[index])
+#if defined(QUALIFIER_PARAM)
+ || (QUALIFIER_PARAM == format[index])
+#endif
+ )
+ {
+ index++;
+ flags |= FLAGS_PRECISION_PARAMETER;
+
+ precision = TrioGetPosition(format, &index);
+ if (precision == NO_POSITION)
+ {
+ parameterPosition++;
+ if (positional)
+ precision = parameterPosition;
+ else
+ {
+ precision = currentParam;
+ currentParam = precision + 1;
+ }
+ }
+ else
+ {
+ if (! positional)
+ currentParam = precision + 1;
+ if (width > maxParam)
+ maxParam = precision;
+ }
+ if (currentParam > maxParam)
+ maxParam = currentParam;
+ }
+ else
+ {
+ precision = trio_to_long(&format[index],
+ &tmpformat,
+ BASE_DECIMAL);
+ index = (int)(tmpformat - format);
+ }
+ }
+ else if (dots == 1) /* Base */
+ {
+ dots++;
+
+ /* After the second dot we have the base */
+ flags |= FLAGS_BASE;
+ if ((QUALIFIER_STAR == format[index])
+#if defined(QUALIFIER_PARAM)
+ || (QUALIFIER_PARAM == format[index])
+#endif
+ )
+ {
+ index++;
+ flags |= FLAGS_BASE_PARAMETER;
+ base = TrioGetPosition(format, &index);
+ if (base == NO_POSITION)
+ {
+ parameterPosition++;
+ if (positional)
+ base = parameterPosition;
+ else
+ {
+ base = currentParam;
+ currentParam = base + 1;
+ }
+ }
+ else
+ {
+ if (! positional)
+ currentParam = base + 1;
+ if (base > maxParam)
+ maxParam = base;
+ }
+ if (currentParam > maxParam)
+ maxParam = currentParam;
+ }
+ else
+ {
+ base = trio_to_long(&format[index],
+ &tmpformat,
+ BASE_DECIMAL);
+ if (base > MAX_BASE)
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
+ index = (int)(tmpformat - format);
+ }
+ }
+ else
+ {
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
+ }
+ break; /* QUALIFIER_DOT */
+
+#if defined(QUALIFIER_PARAM)
+ case QUALIFIER_PARAM:
+ type = TYPE_PRINT;
+ /* FALLTHROUGH */
+#endif
+ case QUALIFIER_STAR:
+ /* This has different meanings for print and scan */
+ if (TYPE_PRINT == type)
+ {
+ /* Read with from parameter */
+ flags |= (FLAGS_WIDTH | FLAGS_WIDTH_PARAMETER);
+ width = TrioGetPosition(format, &index);
+ if (width == NO_POSITION)
+ {
+ parameterPosition++;
+ if (positional)
+ width = parameterPosition;
+ else
+ {
+ width = currentParam;
+ currentParam = width + 1;
+ }
+ }
+ else
+ {
+ if (! positional)
+ currentParam = width + 1;
+ if (width > maxParam)
+ maxParam = width;
+ }
+ if (currentParam > maxParam)
+ maxParam = currentParam;
+ }
+ else
+ {
+ /* Scan, but do not store result */
+ flags |= FLAGS_IGNORE;
+ }
+
+ break; /* QUALIFIER_STAR */
+
+ case '0':
+ if (! (flags & FLAGS_LEFTADJUST))
+ flags |= FLAGS_NILPADDING;
+ /* FALLTHROUGH */
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ flags |= FLAGS_WIDTH;
+ /* &format[index - 1] is used to "rewind" the read
+ * character from format
+ */
+ width = trio_to_long(&format[index - 1],
+ &tmpformat,
+ BASE_DECIMAL);
+ index = (int)(tmpformat - format);
+ break;
+
+ case QUALIFIER_SHORT:
+ if (flags & FLAGS_SHORTSHORT)
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
+ else if (flags & FLAGS_SHORT)
+ flags |= FLAGS_SHORTSHORT;
+ else
+ flags |= FLAGS_SHORT;
+ break;
+
+ case QUALIFIER_LONG:
+ if (flags & FLAGS_QUAD)
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
+ else if (flags & FLAGS_LONG)
+ flags |= FLAGS_QUAD;
+ else
+ flags |= FLAGS_LONG;
+ break;
+
+ case QUALIFIER_LONG_UPPER:
+ flags |= FLAGS_LONGDOUBLE;
+ break;
+
+#if defined(QUALIFIER_SIZE_T)
+ case QUALIFIER_SIZE_T:
+ flags |= FLAGS_SIZE_T;
+ /* Modify flags for later truncation of number */
+ if (sizeof(size_t) == sizeof(trio_ulonglong_t))
+ flags |= FLAGS_QUAD;
+ else if (sizeof(size_t) == sizeof(long))
+ flags |= FLAGS_LONG;
+ break;
+#endif
+
+#if defined(QUALIFIER_PTRDIFF_T)
+ case QUALIFIER_PTRDIFF_T:
+ flags |= FLAGS_PTRDIFF_T;
+ if (sizeof(ptrdiff_t) == sizeof(trio_ulonglong_t))
+ flags |= FLAGS_QUAD;
+ else if (sizeof(ptrdiff_t) == sizeof(long))
+ flags |= FLAGS_LONG;
+ break;
+#endif
+
+#if defined(QUALIFIER_INTMAX_T)
+ case QUALIFIER_INTMAX_T:
+ flags |= FLAGS_INTMAX_T;
+ if (sizeof(trio_intmax_t) == sizeof(trio_ulonglong_t))
+ flags |= FLAGS_QUAD;
+ else if (sizeof(trio_intmax_t) == sizeof(long))
+ flags |= FLAGS_LONG;
+ break;
+#endif
+
+#if defined(QUALIFIER_QUAD)
+ case QUALIFIER_QUAD:
+ flags |= FLAGS_QUAD;
+ break;
+#endif
+
+#if defined(QUALIFIER_FIXED_SIZE)
+ case QUALIFIER_FIXED_SIZE:
+ if (flags & FLAGS_FIXED_SIZE)
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
+
+ if (flags & (FLAGS_ALL_SIZES | FLAGS_LONGDOUBLE |
+ FLAGS_WIDECHAR | FLAGS_VARSIZE_PARAMETER))
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
+
+ if ((format[index] == '6') &&
+ (format[index + 1] == '4'))
+ {
+ varsize = sizeof(trio_int64_t);
+ index += 2;
+ }
+ else if ((format[index] == '3') &&
+ (format[index + 1] == '2'))
+ {
+ varsize = sizeof(trio_int32_t);
+ index += 2;
+ }
+ else if ((format[index] == '1') &&
+ (format[index + 1] == '6'))
+ {
+ varsize = sizeof(trio_int16_t);
+ index += 2;
+ }
+ else if (format[index] == '8')
+ {
+ varsize = sizeof(trio_int8_t);
+ index++;
+ }
+ else
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
+
+ flags |= FLAGS_FIXED_SIZE;
+ break;
+#endif
+
+#if defined(QUALIFIER_WIDECHAR)
+ case QUALIFIER_WIDECHAR:
+ flags |= FLAGS_WIDECHAR;
+ break;
+#endif
+
+#if defined(QUALIFIER_SIZE_T_UPPER)
+ case QUALIFIER_SIZE_T_UPPER:
+ break;
+#endif
+
+#if defined(QUALIFIER_QUOTE)
+ case QUALIFIER_QUOTE:
+ flags |= FLAGS_QUOTE;
+ break;
+#endif
+
+#if defined(QUALIFIER_STICKY)
+ case QUALIFIER_STICKY:
+ flags |= FLAGS_STICKY;
+ gotSticky = TRUE;
+ break;
+#endif
+
+#if defined(QUALIFIER_VARSIZE)
+ case QUALIFIER_VARSIZE:
+ flags |= FLAGS_VARSIZE_PARAMETER;
+ parameterPosition++;
+ if (positional)
+ varsize = parameterPosition;
+ else
+ {
+ varsize = currentParam;
+ currentParam = varsize + 1;
+ }
+ if (currentParam > maxParam)
+ maxParam = currentParam;
+ break;
+#endif
+
+#if defined(QUALIFIER_ROUNDING_UPPER)
+ case QUALIFIER_ROUNDING_UPPER:
+ flags |= FLAGS_ROUNDING;
+ break;
+#endif
+
+ default:
+ /* Bail out completely to make the error more obvious */
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
+ }
+ } /* while qualifier */
+
+ /*
+ * Parameters only need the type and value. The value is
+ * read later.
+ */
+ if (flags & FLAGS_WIDTH_PARAMETER)
+ {
+ usedEntries[width] += 1;
+ parameters[pos].type = FORMAT_PARAMETER;
+ parameters[pos].flags = 0;
+ indices[width] = pos;
+ width = pos++;
+ }
+ if (flags & FLAGS_PRECISION_PARAMETER)
+ {
+ usedEntries[precision] += 1;
+ parameters[pos].type = FORMAT_PARAMETER;
+ parameters[pos].flags = 0;
+ indices[precision] = pos;
+ precision = pos++;
+ }
+ if (flags & FLAGS_BASE_PARAMETER)
+ {
+ usedEntries[base] += 1;
+ parameters[pos].type = FORMAT_PARAMETER;
+ parameters[pos].flags = 0;
+ indices[base] = pos;
+ base = pos++;
+ }
+ if (flags & FLAGS_VARSIZE_PARAMETER)
+ {
+ usedEntries[varsize] += 1;
+ parameters[pos].type = FORMAT_PARAMETER;
+ parameters[pos].flags = 0;
+ indices[varsize] = pos;
+ varsize = pos++;
+ }
+
+ indices[currentParam] = pos;
+
+ switch (format[index++])
+ {
+#if defined(SPECIFIER_CHAR_UPPER)
+ case SPECIFIER_CHAR_UPPER:
+ flags |= FLAGS_WIDECHAR;
+ /* FALLTHROUGH */
+#endif
+ case SPECIFIER_CHAR:
+ if (flags & FLAGS_LONG)
+ flags |= FLAGS_WIDECHAR;
+ else if (flags & FLAGS_SHORT)
+ flags &= ~FLAGS_WIDECHAR;
+ parameters[pos].type = FORMAT_CHAR;
+ break;
+
+#if defined(SPECIFIER_STRING_UPPER)
+ case SPECIFIER_STRING_UPPER:
+ flags |= FLAGS_WIDECHAR;
+ /* FALLTHROUGH */
+#endif
+ case SPECIFIER_STRING:
+ if (flags & FLAGS_LONG)
+ flags |= FLAGS_WIDECHAR;
+ else if (flags & FLAGS_SHORT)
+ flags &= ~FLAGS_WIDECHAR;
+ parameters[pos].type = FORMAT_STRING;
+ break;
+
+ case SPECIFIER_GROUP:
+ if (TYPE_SCAN == type)
+ {
+ int depth = 1;
+ parameters[pos].type = FORMAT_GROUP;
+ if (format[index] == QUALIFIER_CIRCUMFLEX)
+ index++;
+ if (format[index] == SPECIFIER_UNGROUP)
+ index++;
+ if (format[index] == QUALIFIER_MINUS)
+ index++;
+ /* Skip nested brackets */
+ while (format[index] != NIL)
+ {
+ if (format[index] == SPECIFIER_GROUP)
+ {
+ depth++;
+ }
+ else if (format[index] == SPECIFIER_UNGROUP)
+ {
+ if (--depth <= 0)
+ {
+ index++;
+ break;
+ }
+ }
+ index++;
+ }
+ }
+ break;
+
+ case SPECIFIER_INTEGER:
+ parameters[pos].type = FORMAT_INT;
+ break;
+
+ case SPECIFIER_UNSIGNED:
+ flags |= FLAGS_UNSIGNED;
+ parameters[pos].type = FORMAT_INT;
+ break;
+
+ case SPECIFIER_DECIMAL:
+ /* Disable base modifier */
+ flags &= ~FLAGS_BASE_PARAMETER;
+ base = BASE_DECIMAL;
+ parameters[pos].type = FORMAT_INT;
+ break;
+
+ case SPECIFIER_OCTAL:
+ flags |= FLAGS_UNSIGNED;
+ flags &= ~FLAGS_BASE_PARAMETER;
+ base = BASE_OCTAL;
+ parameters[pos].type = FORMAT_INT;
+ break;
+
+#if defined(SPECIFIER_BINARY)
+ case SPECIFIER_BINARY_UPPER:
+ flags |= FLAGS_UPPER;
+ /* FALLTHROUGH */
+ case SPECIFIER_BINARY:
+ flags |= FLAGS_NILPADDING;
+ flags &= ~FLAGS_BASE_PARAMETER;
+ base = BASE_BINARY;
+ parameters[pos].type = FORMAT_INT;
+ break;
+#endif
+
+ case SPECIFIER_HEX_UPPER:
+ flags |= FLAGS_UPPER;
+ /* FALLTHROUGH */
+ case SPECIFIER_HEX:
+ flags |= FLAGS_UNSIGNED;
+ flags &= ~FLAGS_BASE_PARAMETER;
+ base = BASE_HEX;
+ parameters[pos].type = FORMAT_INT;
+ break;
+
+ case SPECIFIER_FLOAT_E_UPPER:
+ flags |= FLAGS_UPPER;
+ /* FALLTHROUGH */
+ case SPECIFIER_FLOAT_E:
+ flags |= FLAGS_FLOAT_E;
+ parameters[pos].type = FORMAT_DOUBLE;
+ break;
+
+ case SPECIFIER_FLOAT_G_UPPER:
+ flags |= FLAGS_UPPER;
+ /* FALLTHROUGH */
+ case SPECIFIER_FLOAT_G:
+ flags |= FLAGS_FLOAT_G;
+ parameters[pos].type = FORMAT_DOUBLE;
+ break;
+
+ case SPECIFIER_FLOAT_F_UPPER:
+ flags |= FLAGS_UPPER;
+ /* FALLTHROUGH */
+ case SPECIFIER_FLOAT_F:
+ parameters[pos].type = FORMAT_DOUBLE;
+ break;
+
+ case SPECIFIER_POINTER:
+ if (sizeof(trio_pointer_t) == sizeof(trio_ulonglong_t))
+ flags |= FLAGS_QUAD;
+ else if (sizeof(trio_pointer_t) == sizeof(long))
+ flags |= FLAGS_LONG;
+ parameters[pos].type = FORMAT_POINTER;
+ break;
+
+ case SPECIFIER_COUNT:
+ parameters[pos].type = FORMAT_COUNT;
+ break;
+
+#if defined(SPECIFIER_HEXFLOAT)
+# if defined(SPECIFIER_HEXFLOAT_UPPER)
+ case SPECIFIER_HEXFLOAT_UPPER:
+ flags |= FLAGS_UPPER;
+ /* FALLTHROUGH */
+# endif
+ case SPECIFIER_HEXFLOAT:
+ base = BASE_HEX;
+ parameters[pos].type = FORMAT_DOUBLE;
+ break;
+#endif
+
+#if defined(FORMAT_ERRNO)
+ case SPECIFIER_ERRNO:
+ parameters[pos].type = FORMAT_ERRNO;
+ break;
+#endif
+
+#if defined(SPECIFIER_USER_DEFINED_BEGIN)
+ case SPECIFIER_USER_DEFINED_BEGIN:
+ {
+ unsigned int max;
+ int without_namespace = TRUE;
+
+ parameters[pos].type = FORMAT_USER_DEFINED;
+ parameters[pos].user_name[0] = NIL;
+ tmpformat = (char *)&format[index];
+
+ while ((ch = format[index]))
+ {
+ index++;
+ if (ch == SPECIFIER_USER_DEFINED_END)
+ {
+ if (without_namespace)
+ {
+ /* We must get the handle first */
+ parameters[pos].type = FORMAT_PARAMETER;
+ parameters[pos].indexAfterSpecifier = index;
+ parameters[pos].flags = FLAGS_USER_DEFINED;
+ /* Adjust parameters for insertion of new one */
+ pos++;
+ usedEntries[currentParam] += 1;
+ parameters[pos].type = FORMAT_USER_DEFINED;
+ currentParam++;
+ indices[currentParam] = pos;
+ if (currentParam > maxParam)
+ maxParam = currentParam;
+ }
+ /* Copy the user data */
+ max = (unsigned int)(&format[index] - tmpformat);
+ if (max > MAX_USER_DATA)
+ max = MAX_USER_DATA;
+ trio_copy_max(parameters[pos].user_data,
+ max,
+ tmpformat);
+ break; /* while */
+ }
+ if (ch == SPECIFIER_USER_DEFINED_SEPARATOR)
+ {
+ without_namespace = FALSE;
+ /* Copy the namespace for later looking-up */
+ max = (int)(&format[index] - tmpformat);
+ if (max > MAX_USER_NAME)
+ max = MAX_USER_NAME;
+ trio_copy_max(parameters[pos].user_name,
+ max,
+ tmpformat);
+ tmpformat = (char *)&format[index];
+ }
+ }
+ if (ch != SPECIFIER_USER_DEFINED_END)
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
+ }
+ break;
+#endif /* defined(SPECIFIER_USER_DEFINED_BEGIN) */
+
+ default:
+ /* Bail out completely to make the error more obvious */
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
+ }
+
+ /* Count the number of times this entry has been used */
+ usedEntries[currentParam] += 1;
+
+ /* Find last sticky parameters */
+ if (gotSticky && !(flags & FLAGS_STICKY))
+ {
+ for (i = pos - 1; i >= 0; i--)
+ {
+ if (parameters[i].type == FORMAT_PARAMETER)
+ continue;
+ if ((parameters[i].flags & FLAGS_STICKY) &&
+ (parameters[i].type == parameters[pos].type))
+ {
+ /* Do not overwrite current qualifiers */
+ flags |= (parameters[i].flags & (unsigned long)~FLAGS_STICKY);
+ if (width == NO_WIDTH)
+ width = parameters[i].width;
+ if (precision == NO_PRECISION)
+ precision = parameters[i].precision;
+ if (base == NO_BASE)
+ base = parameters[i].base;
+ break;
+ }
+ }
+ }
+
+ parameters[pos].indexAfterSpecifier = index;
+ parameters[pos].flags = flags;
+ parameters[pos].width = width;
+ parameters[pos].precision = precision;
+ parameters[pos].base = (base == NO_BASE) ? BASE_DECIMAL : base;
+ parameters[pos].varsize = varsize;
+ pos++;
+
+ if (! positional)
+ parameterPosition++;
+
+ } /* if identifier */
+
+ } /* while format characters left */
+
+ for (num = 0; num <= maxParam; num++)
+ {
+ if (usedEntries[num] != 1)
+ {
+ if (usedEntries[num] == 0) /* gap detected */
+ return TRIO_ERROR_RETURN(TRIO_EGAP, num);
+ else /* double references detected */
+ return TRIO_ERROR_RETURN(TRIO_EDBLREF, num);
+ }
+
+ i = indices[num];
+
+ /*
+ * FORMAT_PARAMETERS are only present if they must be read,
+ * so it makes no sense to check the ignore flag (besides,
+ * the flags variable is not set for that particular type)
+ */
+ if ((parameters[i].type != FORMAT_PARAMETER) &&
+ (parameters[i].flags & FLAGS_IGNORE))
+ continue; /* for all arguments */
+
+ /*
+ * The stack arguments are read according to ANSI C89
+ * default argument promotions:
+ *
+ * char = int
+ * short = int
+ * unsigned char = unsigned int
+ * unsigned short = unsigned int
+ * float = double
+ *
+ * In addition to the ANSI C89 these types are read (the
+ * default argument promotions of C99 has not been
+ * considered yet)
+ *
+ * long long
+ * long double
+ * size_t
+ * ptrdiff_t
+ * intmax_t
+ */
+ switch (parameters[i].type)
+ {
+ case FORMAT_GROUP:
+ case FORMAT_STRING:
+#if TRIO_WIDECHAR
+ if (flags & FLAGS_WIDECHAR)
+ {
+ parameters[i].data.wstring = (argarray == NULL)
+ ? va_arg(*arglist, trio_wchar_t *)
+ : (trio_wchar_t *)(argarray[num]);
+ }
+ else
+#endif
+ {
+ parameters[i].data.string = (argarray == NULL)
+ ? va_arg(*arglist, char *)
+ : (char *)(argarray[num]);
+ }
+ break;
+
+#if defined(FORMAT_USER_DEFINED)
+ case FORMAT_USER_DEFINED:
+#endif
+ case FORMAT_POINTER:
+ case FORMAT_COUNT:
+ case FORMAT_UNKNOWN:
+ parameters[i].data.pointer = (argarray == NULL)
+ ? va_arg(*arglist, trio_pointer_t )
+ : argarray[num];
+ break;
+
+ case FORMAT_CHAR:
+ case FORMAT_INT:
+ if (TYPE_SCAN == type)
+ {
+ if (argarray == NULL)
+ parameters[i].data.pointer =
+ (trio_pointer_t)va_arg(*arglist, trio_pointer_t);
+ else
+ {
+ if (parameters[i].type == FORMAT_CHAR)
+ parameters[i].data.pointer =
+ (trio_pointer_t)((char *)argarray[num]);
+ else if (parameters[i].flags & FLAGS_SHORT)
+ parameters[i].data.pointer =
+ (trio_pointer_t)((short *)argarray[num]);
+ else
+ parameters[i].data.pointer =
+ (trio_pointer_t)((int *)argarray[num]);
+ }
+ }
+ else
+ {
+#if defined(QUALIFIER_VARSIZE) || defined(QUALIFIER_FIXED_SIZE)
+ if (parameters[i].flags
+ & (FLAGS_VARSIZE_PARAMETER | FLAGS_FIXED_SIZE))
+ {
+ if (parameters[i].flags & FLAGS_VARSIZE_PARAMETER)
+ {
+ /*
+ * Variable sizes are mapped onto the fixed sizes, in
+ * accordance with integer promotion.
+ *
+ * Please note that this may not be portable, as we
+ * only guess the size, not the layout of the numbers.
+ * For example, if int is little-endian, and long is
+ * big-endian, then this will fail.
+ */
+ varsize = (int)parameters[parameters[i].varsize].data.number.as_unsigned;
+ }
+ else
+ {
+ /* Used for the I<bits> modifiers */
+ varsize = parameters[i].varsize;
+ }
+ parameters[i].flags &= ~FLAGS_ALL_VARSIZES;
+
+ if (varsize <= (int)sizeof(int))
+ ;
+ else if (varsize <= (int)sizeof(long))
+ parameters[i].flags |= FLAGS_LONG;
+#if defined(QUALIFIER_INTMAX_T)
+ else if (varsize <= (int)sizeof(trio_longlong_t))
+ parameters[i].flags |= FLAGS_QUAD;
+ else
+ parameters[i].flags |= FLAGS_INTMAX_T;
+#else
+ else
+ parameters[i].flags |= FLAGS_QUAD;
+#endif
+ }
+#endif /* defined(QUALIFIER_VARSIZE) */
+#if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
+ if (parameters[i].flags & FLAGS_SIZE_T)
+ parameters[i].data.number.as_unsigned = (argarray == NULL)
+ ? (trio_uintmax_t)va_arg(*arglist, size_t)
+ : (trio_uintmax_t)(*((size_t *)argarray[num]));
+ else
+#endif
+#if defined(QUALIFIER_PTRDIFF_T)
+ if (parameters[i].flags & FLAGS_PTRDIFF_T)
+ parameters[i].data.number.as_unsigned = (argarray == NULL)
+ ? (trio_uintmax_t)va_arg(*arglist, ptrdiff_t)
+ : (trio_uintmax_t)(*((ptrdiff_t *)argarray[num]));
+ else
+#endif
+#if defined(QUALIFIER_INTMAX_T)
+ if (parameters[i].flags & FLAGS_INTMAX_T)
+ parameters[i].data.number.as_unsigned = (argarray == NULL)
+ ? (trio_uintmax_t)va_arg(*arglist, trio_intmax_t)
+ : (trio_uintmax_t)(*((trio_intmax_t *)argarray[num]));
+ else
+#endif
+ if (parameters[i].flags & FLAGS_QUAD)
+ parameters[i].data.number.as_unsigned = (argarray == NULL)
+ ? (trio_uintmax_t)va_arg(*arglist, trio_ulonglong_t)
+ : (trio_uintmax_t)(*((trio_ulonglong_t *)argarray[num]));
+ else if (parameters[i].flags & FLAGS_LONG)
+ parameters[i].data.number.as_unsigned = (argarray == NULL)
+ ? (trio_uintmax_t)va_arg(*arglist, long)
+ : (trio_uintmax_t)(*((long *)argarray[num]));
+ else
+ {
+ if (argarray == NULL)
+ parameters[i].data.number.as_unsigned = (trio_uintmax_t)va_arg(*arglist, int);
+ else
+ {
+ if (parameters[i].type == FORMAT_CHAR)
+ parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((char *)argarray[num]));
+ else if (parameters[i].flags & FLAGS_SHORT)
+ parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((short *)argarray[num]));
+ else
+ parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((int *)argarray[num]));
+ }
+ }
+ }
+ break;
+
+ case FORMAT_PARAMETER:
+ /*
+ * The parameter for the user-defined specifier is a pointer,
+ * whereas the rest (width, precision, base) uses an integer.
+ */
+ if (parameters[i].flags & FLAGS_USER_DEFINED)
+ parameters[i].data.pointer = (argarray == NULL)
+ ? va_arg(*arglist, trio_pointer_t )
+ : argarray[num];
+ else
+ parameters[i].data.number.as_unsigned = (argarray == NULL)
+ ? (trio_uintmax_t)va_arg(*arglist, int)
+ : (trio_uintmax_t)(*((int *)argarray[num]));
+ break;
+
+ case FORMAT_DOUBLE:
+ if (TYPE_SCAN == type)
+ {
+ if (parameters[i].flags & FLAGS_LONGDOUBLE)
+ parameters[i].data.longdoublePointer = (argarray == NULL)
+ ? va_arg(*arglist, trio_long_double_t *)
+ : (trio_long_double_t *)argarray[num];
+ else
+ {
+ if (parameters[i].flags & FLAGS_LONG)
+ parameters[i].data.doublePointer = (argarray == NULL)
+ ? va_arg(*arglist, double *)
+ : (double *)argarray[num];
+ else
+ parameters[i].data.doublePointer = (argarray == NULL)
+ ? (double *)va_arg(*arglist, float *)
+ : (double *)((float *)argarray[num]);
+ }
+ }
+ else
+ {
+ if (parameters[i].flags & FLAGS_LONGDOUBLE)
+ parameters[i].data.longdoubleNumber = (argarray == NULL)
+ ? va_arg(*arglist, trio_long_double_t)
+ : (trio_long_double_t)(*((trio_long_double_t *)argarray[num]));
+ else
+ {
+ if (argarray == NULL)
+ parameters[i].data.longdoubleNumber =
+ (trio_long_double_t)va_arg(*arglist, double);
+ else
+ {
+ if (parameters[i].flags & FLAGS_SHORT)
+ parameters[i].data.longdoubleNumber =
+ (trio_long_double_t)(*((float *)argarray[num]));
+ else
+ parameters[i].data.longdoubleNumber =
+ (trio_long_double_t)(*((double *)argarray[num]));
+ }
+ }
+ }
+ break;
+
+#if defined(FORMAT_ERRNO)
+ case FORMAT_ERRNO:
+ parameters[i].data.errorNumber = save_errno;
+ break;
+#endif
+
+ default:
+ break;
+ }
+ } /* for all specifiers */
+ return num;
+}
+
+
+/*************************************************************************
+ *
+ * FORMATTING
+ *
+ ************************************************************************/
+
+
+/*************************************************************************
+ * TrioWriteNumber
+ *
+ * Description:
+ * Output a number.
+ * The complexity of this function is a result of the complexity
+ * of the dependencies of the flags.
+ */
+TRIO_PRIVATE void
+TrioWriteNumber
+TRIO_ARGS6((self, number, flags, width, precision, base),
+ trio_class_t *self,
+ trio_uintmax_t number,
+ trio_flags_t flags,
+ int width,
+ int precision,
+ int base)
+{
+ BOOLEAN_T isNegative;
+ BOOLEAN_T isNumberZero;
+ BOOLEAN_T isPrecisionZero;
+ BOOLEAN_T ignoreNumber;
+ char buffer[MAX_CHARS_IN(trio_uintmax_t) * (1 + MAX_LOCALE_SEPARATOR_LENGTH) + 1];
+ char *bufferend;
+ char *pointer;
+ TRIO_CONST char *digits;
+ int i;
+ int length;
+ char *p;
+ int count;
+
+ assert(VALID(self));
+ assert(VALID(self->OutStream));
+ assert(((base >= MIN_BASE) && (base <= MAX_BASE)) || (base == NO_BASE));
+
+ digits = (flags & FLAGS_UPPER) ? internalDigitsUpper : internalDigitsLower;
+ if (base == NO_BASE)
+ base = BASE_DECIMAL;
+
+ isNumberZero = (number == 0);
+ isPrecisionZero = (precision == 0);
+ ignoreNumber = (isNumberZero
+ && isPrecisionZero
+ && !((flags & FLAGS_ALTERNATIVE) && (base == BASE_OCTAL)));
+
+ if (flags & FLAGS_UNSIGNED)
+ {
+ isNegative = FALSE;
+ flags &= ~FLAGS_SHOWSIGN;
+ }
+ else
+ {
+ isNegative = ((trio_intmax_t)number < 0);
+ if (isNegative)
+ number = -((trio_intmax_t)number);
+ }
+
+ if (flags & FLAGS_QUAD)
+ number &= (trio_ulonglong_t)-1;
+ else if (flags & FLAGS_LONG)
+ number &= (unsigned long)-1;
+ else
+ number &= (unsigned int)-1;
+
+ /* Build number */
+ pointer = bufferend = &buffer[sizeof(buffer) - 1];
+ *pointer-- = NIL;
+ for (i = 1; i < (int)sizeof(buffer); i++)
+ {
+ *pointer-- = digits[number % base];
+ number /= base;
+ if (number == 0)
+ break;
+
+ if ((flags & FLAGS_QUOTE) && TrioFollowedBySeparator(i + 1))
+ {
+ /*
+ * We are building the number from the least significant
+ * to the most significant digit, so we have to copy the
+ * thousand separator backwards
+ */
+ length = internalThousandSeparatorLength;
+ if (((int)(pointer - buffer) - length) > 0)
+ {
+ p = &internalThousandSeparator[length - 1];
+ while (length-- > 0)
+ *pointer-- = *p--;
+ }
+ }
+ }
+
+ if (! ignoreNumber)
+ {
+ /* Adjust width */
+ width -= (bufferend - pointer) - 1;
+ }
+
+ /* Adjust precision */
+ if (NO_PRECISION != precision)
+ {
+ precision -= (bufferend - pointer) - 1;
+ if (precision < 0)
+ precision = 0;
+ flags |= FLAGS_NILPADDING;
+ }
+
+ /* Calculate padding */
+ count = (! ((flags & FLAGS_LEFTADJUST) || (precision == NO_PRECISION)))
+ ? precision
+ : 0;
+
+ /* Adjust width further */
+ if (isNegative || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE))
+ width--;
+ if ((flags & FLAGS_ALTERNATIVE) && !isNumberZero)
+ {
+ switch (base)
+ {
+ case BASE_BINARY:
+ case BASE_HEX:
+ width -= 2;
+ break;
+ case BASE_OCTAL:
+ if (!(flags & FLAGS_NILPADDING) || (count == 0))
+ width--;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Output prefixes spaces if needed */
+ if (! ((flags & FLAGS_LEFTADJUST) ||
+ ((flags & FLAGS_NILPADDING) && (precision == NO_PRECISION))))
+ {
+ while (width-- > count)
+ self->OutStream(self, CHAR_ADJUST);
+ }
+
+ /* width has been adjusted for signs and alternatives */
+ if (isNegative)
+ self->OutStream(self, '-');
+ else if (flags & FLAGS_SHOWSIGN)
+ self->OutStream(self, '+');
+ else if (flags & FLAGS_SPACE)
+ self->OutStream(self, ' ');
+
+ /* Prefix is not written when the value is zero */
+ if ((flags & FLAGS_ALTERNATIVE) && !isNumberZero)
+ {
+ switch (base)
+ {
+ case BASE_BINARY:
+ self->OutStream(self, '0');
+ self->OutStream(self, (flags & FLAGS_UPPER) ? 'B' : 'b');
+ break;
+
+ case BASE_OCTAL:
+ if (!(flags & FLAGS_NILPADDING) || (count == 0))
+ self->OutStream(self, '0');
+ break;
+
+ case BASE_HEX:
+ self->OutStream(self, '0');
+ self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x');
+ break;
+
+ default:
+ break;
+ } /* switch base */
+ }
+
+ /* Output prefixed zero padding if needed */
+ if (flags & FLAGS_NILPADDING)
+ {
+ if (precision == NO_PRECISION)
+ precision = width;
+ while (precision-- > 0)
+ {
+ self->OutStream(self, '0');
+ width--;
+ }
+ }
+
+ if (! ignoreNumber)
+ {
+ /* Output the number itself */
+ while (*(++pointer))
+ {
+ self->OutStream(self, *pointer);
+ }
+ }
+
+ /* Output trailing spaces if needed */
+ if (flags & FLAGS_LEFTADJUST)
+ {
+ while (width-- > 0)
+ self->OutStream(self, CHAR_ADJUST);
+ }
+}
+
+/*************************************************************************
+ * TrioWriteStringCharacter
+ *
+ * Description:
+ * Output a single character of a string
+ */
+TRIO_PRIVATE void
+TrioWriteStringCharacter
+TRIO_ARGS3((self, ch, flags),
+ trio_class_t *self,
+ int ch,
+ trio_flags_t flags)
+{
+ if (flags & FLAGS_ALTERNATIVE)
+ {
+ if (! isprint(ch))
+ {
+ /*
+ * Non-printable characters are converted to C escapes or
+ * \number, if no C escape exists.
+ */
+ self->OutStream(self, CHAR_BACKSLASH);
+ switch (ch)
+ {
+ case '\007': self->OutStream(self, 'a'); break;
+ case '\b': self->OutStream(self, 'b'); break;
+ case '\f': self->OutStream(self, 'f'); break;
+ case '\n': self->OutStream(self, 'n'); break;
+ case '\r': self->OutStream(self, 'r'); break;
+ case '\t': self->OutStream(self, 't'); break;
+ case '\v': self->OutStream(self, 'v'); break;
+ case '\\': self->OutStream(self, '\\'); break;
+ default:
+ self->OutStream(self, 'x');
+ TrioWriteNumber(self, (trio_uintmax_t)ch,
+ FLAGS_UNSIGNED | FLAGS_NILPADDING,
+ 2, 2, BASE_HEX);
+ break;
+ }
+ }
+ else if (ch == CHAR_BACKSLASH)
+ {
+ self->OutStream(self, CHAR_BACKSLASH);
+ self->OutStream(self, CHAR_BACKSLASH);
+ }
+ else
+ {
+ self->OutStream(self, ch);
+ }
+ }
+ else
+ {
+ self->OutStream(self, ch);
+ }
+}
+
+/*************************************************************************
+ * TrioWriteString
+ *
+ * Description:
+ * Output a string
+ */
+TRIO_PRIVATE void
+TrioWriteString
+TRIO_ARGS5((self, string, flags, width, precision),
+ trio_class_t *self,
+ TRIO_CONST char *string,
+ trio_flags_t flags,
+ int width,
+ int precision)
+{
+ int length;
+ int ch;
+
+ assert(VALID(self));
+ assert(VALID(self->OutStream));
+
+ if (string == NULL)
+ {
+ string = internalNullString;
+ length = sizeof(internalNullString) - 1;
+ /* Disable quoting for the null pointer */
+ flags &= (~FLAGS_QUOTE);
+ width = 0;
+ }
+ else
+ {
+ length = trio_length(string);
+ }
+ if ((NO_PRECISION != precision) &&
+ (precision < length))
+ {
+ length = precision;
+ }
+ width -= length;
+
+ if (flags & FLAGS_QUOTE)
+ self->OutStream(self, CHAR_QUOTE);
+
+ if (! (flags & FLAGS_LEFTADJUST))
+ {
+ while (width-- > 0)
+ self->OutStream(self, CHAR_ADJUST);
+ }
+
+ while (length-- > 0)
+ {
+ /* The ctype parameters must be an unsigned char (or EOF) */
+ ch = (int)((unsigned char)(*string++));
+ TrioWriteStringCharacter(self, ch, flags);
+ }
+
+ if (flags & FLAGS_LEFTADJUST)
+ {
+ while (width-- > 0)
+ self->OutStream(self, CHAR_ADJUST);
+ }
+ if (flags & FLAGS_QUOTE)
+ self->OutStream(self, CHAR_QUOTE);
+}
+
+/*************************************************************************
+ * TrioWriteWideStringCharacter
+ *
+ * Description:
+ * Output a wide string as a multi-byte sequence
+ */
+#if TRIO_WIDECHAR
+TRIO_PRIVATE int
+TrioWriteWideStringCharacter
+TRIO_ARGS4((self, wch, flags, width),
+ trio_class_t *self,
+ trio_wchar_t wch,
+ trio_flags_t flags,
+ int width)
+{
+ int size;
+ int i;
+ int ch;
+ char *string;
+ char buffer[MB_LEN_MAX + 1];
+
+ if (width == NO_WIDTH)
+ width = sizeof(buffer);
+
+ size = wctomb(buffer, wch);
+ if ((size <= 0) || (size > width) || (buffer[0] == NIL))
+ return 0;
+
+ string = buffer;
+ i = size;
+ while ((width >= i) && (width-- > 0) && (i-- > 0))
+ {
+ /* The ctype parameters must be an unsigned char (or EOF) */
+ ch = (int)((unsigned char)(*string++));
+ TrioWriteStringCharacter(self, ch, flags);
+ }
+ return size;
+}
+#endif /* TRIO_WIDECHAR */
+
+/*************************************************************************
+ * TrioWriteWideString
+ *
+ * Description:
+ * Output a wide character string as a multi-byte string
+ */
+#if TRIO_WIDECHAR
+TRIO_PRIVATE void
+TrioWriteWideString
+TRIO_ARGS5((self, wstring, flags, width, precision),
+ trio_class_t *self,
+ TRIO_CONST trio_wchar_t *wstring,
+ trio_flags_t flags,
+ int width,
+ int precision)
+{
+ int length;
+ int size;
+
+ assert(VALID(self));
+ assert(VALID(self->OutStream));
+
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
+ (void)mblen(NULL, 0);
+#endif
+
+ if (wstring == NULL)
+ {
+ TrioWriteString(self, NULL, flags, width, precision);
+ return;
+ }
+
+ if (NO_PRECISION == precision)
+ {
+ length = INT_MAX;
+ }
+ else
+ {
+ length = precision;
+ width -= length;
+ }
+
+ if (flags & FLAGS_QUOTE)
+ self->OutStream(self, CHAR_QUOTE);
+
+ if (! (flags & FLAGS_LEFTADJUST))
+ {
+ while (width-- > 0)
+ self->OutStream(self, CHAR_ADJUST);
+ }
+
+ while (length > 0)
+ {
+ size = TrioWriteWideStringCharacter(self, *wstring++, flags, length);
+ if (size == 0)
+ break; /* while */
+ length -= size;
+ }
+
+ if (flags & FLAGS_LEFTADJUST)
+ {
+ while (width-- > 0)
+ self->OutStream(self, CHAR_ADJUST);
+ }
+ if (flags & FLAGS_QUOTE)
+ self->OutStream(self, CHAR_QUOTE);
+}
+#endif /* TRIO_WIDECHAR */
+
+/*************************************************************************
+ * TrioWriteDouble
+ *
+ * http://wwwold.dkuug.dk/JTC1/SC22/WG14/www/docs/dr_211.htm
+ *
+ * "5.2.4.2.2 paragraph #4
+ *
+ * The accuracy [...] is implementation defined, as is the accuracy
+ * of the conversion between floating-point internal representations
+ * and string representations performed by the libray routine in
+ * <stdio.h>"
+ */
+/* FIXME: handle all instances of constant long-double number (L)
+ * and *l() math functions.
+ */
+TRIO_PRIVATE void
+TrioWriteDouble
+TRIO_ARGS6((self, number, flags, width, precision, base),
+ trio_class_t *self,
+ trio_long_double_t number,
+ trio_flags_t flags,
+ int width,
+ int precision,
+ int base)
+{
+ trio_long_double_t integerNumber;
+ trio_long_double_t fractionNumber;
+ trio_long_double_t workNumber;
+ int integerDigits;
+ int fractionDigits;
+ int exponentDigits;
+ int baseDigits;
+ int integerThreshold;
+ int fractionThreshold;
+ int expectedWidth;
+ int exponent = 0;
+ unsigned int uExponent = 0;
+ int exponentBase;
+ trio_long_double_t dblBase;
+ trio_long_double_t dblIntegerBase;
+ trio_long_double_t dblFractionBase;
+ trio_long_double_t integerAdjust;
+ trio_long_double_t fractionAdjust;
+ BOOLEAN_T isNegative;
+ BOOLEAN_T isExponentNegative = FALSE;
+ BOOLEAN_T requireTwoDigitExponent;
+ BOOLEAN_T isHex;
+ TRIO_CONST char *digits;
+ char *groupingPointer;
+ int i;
+ int index;
+ BOOLEAN_T hasOnlyZeroes;
+ int zeroes = 0;
+ register int trailingZeroes;
+ BOOLEAN_T keepTrailingZeroes;
+ BOOLEAN_T keepDecimalPoint;
+ trio_long_double_t epsilon;
+
+ assert(VALID(self));
+ assert(VALID(self->OutStream));
+ assert(((base >= MIN_BASE) && (base <= MAX_BASE)) || (base == NO_BASE));
+
+ /* Determine sign and look for special quantities */
+ switch (trio_fpclassify_and_signbit(number, &isNegative))
+ {
+ case TRIO_FP_NAN:
+ TrioWriteString(self,
+ (flags & FLAGS_UPPER)
+ ? NAN_UPPER
+ : NAN_LOWER,
+ flags, width, precision);
+ return;
+
+ case TRIO_FP_INFINITE:
+ if (isNegative)
+ {
+ /* Negative infinity */
+ TrioWriteString(self,
+ (flags & FLAGS_UPPER)
+ ? "-" INFINITE_UPPER
+ : "-" INFINITE_LOWER,
+ flags, width, precision);
+ return;
+ }
+ else
+ {
+ /* Positive infinity */
+ TrioWriteString(self,
+ (flags & FLAGS_UPPER)
+ ? INFINITE_UPPER
+ : INFINITE_LOWER,
+ flags, width, precision);
+ return;
+ }
+
+ default:
+ /* Finitude */
+ break;
+ }
+
+ /* Normal numbers */
+ if (flags & FLAGS_LONGDOUBLE)
+ {
+ baseDigits = (base == 10)
+ ? LDBL_DIG
+ : (int)floor(LDBL_MANT_DIG / TrioLogarithmBase(base));
+ epsilon = LDBL_EPSILON;
+ }
+ else if (flags & FLAGS_SHORT)
+ {
+ baseDigits = (base == BASE_DECIMAL)
+ ? FLT_DIG
+ : (int)floor(FLT_MANT_DIG / TrioLogarithmBase(base));
+ epsilon = FLT_EPSILON;
+ }
+ else
+ {
+ baseDigits = (base == BASE_DECIMAL)
+ ? DBL_DIG
+ : (int)floor(DBL_MANT_DIG / TrioLogarithmBase(base));
+ epsilon = DBL_EPSILON;
+ }
+
+ digits = (flags & FLAGS_UPPER) ? internalDigitsUpper : internalDigitsLower;
+ isHex = (base == BASE_HEX);
+ if (base == NO_BASE)
+ base = BASE_DECIMAL;
+ dblBase = (trio_long_double_t)base;
+ keepTrailingZeroes = !( (flags & FLAGS_ROUNDING) ||
+ ( (flags & FLAGS_FLOAT_G) &&
+ !(flags & FLAGS_ALTERNATIVE) ) );
+
+ if (flags & FLAGS_ROUNDING)
+ precision = baseDigits;
+
+ if (precision == NO_PRECISION)
+ {
+ if (isHex)
+ {
+ keepTrailingZeroes = FALSE;
+ precision = FLT_MANT_DIG;
+ }
+ else
+ {
+ precision = FLT_DIG;
+ }
+ }
+
+ if (isNegative)
+ number = -number;
+
+ if (isHex)
+ flags |= FLAGS_FLOAT_E;
+
+ if (flags & FLAGS_FLOAT_G)
+ {
+ if (precision == 0)
+ precision = 1;
+
+ if ((number < 1.0E-4) || (number > powl(base,
+ (trio_long_double_t)precision)))
+ {
+ /* Use scientific notation */
+ flags |= FLAGS_FLOAT_E;
+ }
+ else if (number < 1.0)
+ {
+ /*
+ * Use normal notation. If the integer part of the number is
+ * zero, then adjust the precision to include leading fractional
+ * zeros.
+ */
+ workNumber = TrioLogarithm(number, base);
+ workNumber = TRIO_FABS(workNumber);
+ if (workNumber - floorl(workNumber) < 0.001)
+ workNumber--;
+ zeroes = (int)floorl(workNumber);
+ }
+ }
+
+ if (flags & FLAGS_FLOAT_E)
+ {
+ /* Scale the number */
+ workNumber = TrioLogarithm(number, base);
+ if (trio_isinf(workNumber) == -1)
+ {
+ exponent = 0;
+ /* Undo setting */
+ if (flags & FLAGS_FLOAT_G)
+ flags &= ~FLAGS_FLOAT_E;
+ }
+ else
+ {
+ exponent = (int)floorl(workNumber);
+ number /= powl(dblBase, (trio_long_double_t)exponent);
+ isExponentNegative = (exponent < 0);
+ uExponent = (isExponentNegative) ? -exponent : exponent;
+ if (isHex)
+ uExponent *= 4; /* log16(2) */
+ /* No thousand separators */
+ flags &= ~FLAGS_QUOTE;
+ }
+ }
+
+ integerNumber = floorl(number);
+ fractionNumber = number - integerNumber;
+
+ /*
+ * Truncated number.
+ *
+ * Precision is number of significant digits for FLOAT_G
+ * and number of fractional digits for others.
+ */
+ integerDigits = (integerNumber > epsilon)
+ ? 1 + (int)TrioLogarithm(integerNumber, base)
+ : 1;
+ fractionDigits = ((flags & FLAGS_FLOAT_G) && (zeroes == 0))
+ ? precision - integerDigits
+ : zeroes + precision;
+
+ dblFractionBase = TrioPower(base, fractionDigits);
+
+ workNumber = number + 0.5 / dblFractionBase;
+ if (floorl(number) != floorl(workNumber))
+ {
+ if (flags & FLAGS_FLOAT_E)
+ {
+ /* Adjust if number was rounded up one digit (ie. 0.99 to 1.00) */
+ exponent++;
+ isExponentNegative = (exponent < 0);
+ uExponent = (isExponentNegative) ? -exponent : exponent;
+ if (isHex)
+ uExponent *= 4; /* log16(2) */
+ workNumber = (number + 0.5 / dblFractionBase) / dblBase;
+ integerNumber = floorl(workNumber);
+ fractionNumber = workNumber - integerNumber;
+ }
+ else
+ {
+ /* Adjust if number was rounded up one digit (ie. 99 to 100) */
+ integerNumber = floorl(number + 0.5);
+ fractionNumber = 0.0;
+ integerDigits = (integerNumber > epsilon)
+ ? 1 + (int)TrioLogarithm(integerNumber, base)
+ : 1;
+ }
+ }
+
+ /* Estimate accuracy */
+ integerAdjust = fractionAdjust = 0.5;
+ if (flags & FLAGS_ROUNDING)
+ {
+ if (integerDigits > baseDigits)
+ {
+ integerThreshold = baseDigits;
+ fractionDigits = 0;
+ dblFractionBase = 1.0;
+ fractionThreshold = 0;
+ precision = 0; /* Disable decimal-point */
+ integerAdjust = TrioPower(base, integerDigits - integerThreshold - 1);
+ fractionAdjust = 0.0;
+ }
+ else
+ {
+ integerThreshold = integerDigits;
+ fractionThreshold = fractionDigits - integerThreshold;
+ fractionAdjust = 1.0;
+ }
+ }
+ else
+ {
+ integerThreshold = INT_MAX;
+ fractionThreshold = INT_MAX;
+ }
+
+ /*
+ * Calculate expected width.
+ * sign + integer part + thousands separators + decimal point
+ * + fraction + exponent
+ */
+ fractionAdjust /= dblFractionBase;
+ hasOnlyZeroes = (floorl((fractionNumber + fractionAdjust) * dblFractionBase) < epsilon);
+ keepDecimalPoint = ( (flags & FLAGS_ALTERNATIVE) ||
+ !((precision == 0) ||
+ (!keepTrailingZeroes && hasOnlyZeroes)) );
+ if (flags & FLAGS_FLOAT_E)
+ {
+ exponentDigits = (uExponent == 0)
+ ? 1
+ : (int)ceil(TrioLogarithm((double)(uExponent + 1),
+ (isHex) ? 10.0 : base));
+ }
+ else
+ exponentDigits = 0;
+ requireTwoDigitExponent = ((base == BASE_DECIMAL) && (exponentDigits == 1));
+
+ expectedWidth = integerDigits + fractionDigits
+ + (keepDecimalPoint
+ ? internalDecimalPointLength
+ : 0)
+ + ((flags & FLAGS_QUOTE)
+ ? TrioCalcThousandSeparatorLength(integerDigits)
+ : 0);
+ if (isNegative || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE))
+ expectedWidth += sizeof("-") - 1;
+ if (exponentDigits > 0)
+ expectedWidth += exponentDigits +
+ ((requireTwoDigitExponent ? sizeof("E+0") : sizeof("E+")) - 1);
+ if (isHex)
+ expectedWidth += sizeof("0X") - 1;
+
+ /* Output prefixing */
+ if (flags & FLAGS_NILPADDING)
+ {
+ /* Leading zeros must be after sign */
+ if (isNegative)
+ self->OutStream(self, '-');
+ else if (flags & FLAGS_SHOWSIGN)
+ self->OutStream(self, '+');
+ else if (flags & FLAGS_SPACE)
+ self->OutStream(self, ' ');
+ if (isHex)
+ {
+ self->OutStream(self, '0');
+ self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x');
+ }
+ if (!(flags & FLAGS_LEFTADJUST))
+ {
+ for (i = expectedWidth; i < width; i++)
+ {
+ self->OutStream(self, '0');
+ }
+ }
+ }
+ else
+ {
+ /* Leading spaces must be before sign */
+ if (!(flags & FLAGS_LEFTADJUST))
+ {
+ for (i = expectedWidth; i < width; i++)
+ {
+ self->OutStream(self, CHAR_ADJUST);
+ }
+ }
+ if (isNegative)
+ self->OutStream(self, '-');
+ else if (flags & FLAGS_SHOWSIGN)
+ self->OutStream(self, '+');
+ else if (flags & FLAGS_SPACE)
+ self->OutStream(self, ' ');
+ if (isHex)
+ {
+ self->OutStream(self, '0');
+ self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x');
+ }
+ }
+
+ /* Output the integer part and thousand separators */
+ dblIntegerBase = 1.0 / TrioPower(base, integerDigits - 1);
+ for (i = 0; i < integerDigits; i++)
+ {
+ workNumber = floorl(((integerNumber + integerAdjust) * dblIntegerBase));
+ if (i > integerThreshold)
+ {
+ /* Beyond accuracy */
+ self->OutStream(self, digits[0]);
+ }
+ else
+ {
+ self->OutStream(self, digits[(int)fmodl(workNumber, dblBase)]);
+ }
+ dblIntegerBase *= dblBase;
+
+ if (((flags & (FLAGS_FLOAT_E | FLAGS_QUOTE)) == FLAGS_QUOTE)
+ && TrioFollowedBySeparator(integerDigits - i))
+ {
+ for (groupingPointer = internalThousandSeparator;
+ *groupingPointer != NIL;
+ groupingPointer++)
+ {
+ self->OutStream(self, *groupingPointer);
+ }
+ }
+ }
+
+ /* Insert decimal point and build the fraction part */
+ trailingZeroes = 0;
+
+ if (keepDecimalPoint)
+ {
+ if (internalDecimalPoint)
+ {
+ self->OutStream(self, internalDecimalPoint);
+ }
+ else
+ {
+ for (i = 0; i < internalDecimalPointLength; i++)
+ {
+ self->OutStream(self, internalDecimalPointString[i]);
+ }
+ }
+ }
+
+ for (i = 0; i < fractionDigits; i++)
+ {
+ if ((integerDigits > integerThreshold) || (i > fractionThreshold))
+ {
+ /* Beyond accuracy */
+ trailingZeroes++;
+ }
+ else
+ {
+ fractionNumber *= dblBase;
+ fractionAdjust *= dblBase;
+ workNumber = floorl(fractionNumber + fractionAdjust);
+ fractionNumber -= workNumber;
+ index = (int)fmodl(workNumber, dblBase);
+ if (index == 0)
+ {
+ trailingZeroes++;
+ }
+ else
+ {
+ while (trailingZeroes > 0)
+ {
+ /* Not trailing zeroes after all */
+ self->OutStream(self, digits[0]);
+ trailingZeroes--;
+ }
+ self->OutStream(self, digits[index]);
+ }
+ }
+ }
+
+ if (keepTrailingZeroes)
+ {
+ while (trailingZeroes > 0)
+ {
+ self->OutStream(self, digits[0]);
+ trailingZeroes--;
+ }
+ }
+
+ /* Output exponent */
+ if (exponentDigits > 0)
+ {
+ self->OutStream(self,
+ isHex
+ ? ((flags & FLAGS_UPPER) ? 'P' : 'p')
+ : ((flags & FLAGS_UPPER) ? 'E' : 'e'));
+ self->OutStream(self, (isExponentNegative) ? '-' : '+');
+
+ /* The exponent must contain at least two digits */
+ if (requireTwoDigitExponent)
+ self->OutStream(self, '0');
+
+ if (isHex)
+ base = 10.0;
+ exponentBase = (int)TrioPower(base, exponentDigits - 1);
+ for (i = 0; i < exponentDigits; i++)
+ {
+ self->OutStream(self, digits[(uExponent / exponentBase) % base]);
+ exponentBase /= base;
+ }
+ }
+ /* Output trailing spaces */
+ if (flags & FLAGS_LEFTADJUST)
+ {
+ for (i = expectedWidth; i < width; i++)
+ {
+ self->OutStream(self, CHAR_ADJUST);
+ }
+ }
+}
+
+/*************************************************************************
+ * TrioFormatProcess
+ *
+ * Description:
+ * This is the main engine for formatting output
+ */
+TRIO_PRIVATE int
+TrioFormatProcess
+TRIO_ARGS3((data, format, parameters),
+ trio_class_t *data,
+ TRIO_CONST char *format,
+ trio_parameter_t *parameters)
+{
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
+ int charlen;
+#endif
+ int i;
+ TRIO_CONST char *string;
+ trio_pointer_t pointer;
+ trio_flags_t flags;
+ int width;
+ int precision;
+ int base;
+ int index;
+
+ index = 0;
+ i = 0;
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
+ (void)mblen(NULL, 0);
+#endif
+
+ while (format[index])
+ {
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
+ if (! isascii(format[index]))
+ {
+ charlen = mblen(&format[index], MB_LEN_MAX);
+ /*
+ * Only valid multibyte characters are handled here. Invalid
+ * multibyte characters (charlen == -1) are handled as normal
+ * characters.
+ */
+ if (charlen != -1)
+ {
+ while (charlen-- > 0)
+ {
+ data->OutStream(data, format[index++]);
+ }
+ continue; /* while characters left in formatting string */
+ }
+ }
+#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
+ if (CHAR_IDENTIFIER == format[index])
+ {
+ if (CHAR_IDENTIFIER == format[index + 1])
+ {
+ data->OutStream(data, CHAR_IDENTIFIER);
+ index += 2;
+ }
+ else
+ {
+ /* Skip the parameter entries */
+ while (parameters[i].type == FORMAT_PARAMETER)
+ i++;
+
+ flags = parameters[i].flags;
+
+ /* Find width */
+ width = parameters[i].width;
+ if (flags & FLAGS_WIDTH_PARAMETER)
+ {
+ /* Get width from parameter list */
+ width = (int)parameters[width].data.number.as_signed;
+ if (width < 0)
+ {
+ /*
+ * A negative width is the same as the - flag and
+ * a positive width.
+ */
+ flags |= FLAGS_LEFTADJUST;
+ flags &= ~FLAGS_NILPADDING;
+ width = -width;
+ }
+ }
+
+ /* Find precision */
+ if (flags & FLAGS_PRECISION)
+ {
+ precision = parameters[i].precision;
+ if (flags & FLAGS_PRECISION_PARAMETER)
+ {
+ /* Get precision from parameter list */
+ precision = (int)parameters[precision].data.number.as_signed;
+ if (precision < 0)
+ {
+ /*
+ * A negative precision is the same as no
+ * precision
+ */
+ precision = NO_PRECISION;
+ }
+ }
+ }
+ else
+ {
+ precision = NO_PRECISION;
+ }
+
+ /* Find base */
+ base = parameters[i].base;
+ if (flags & FLAGS_BASE_PARAMETER)
+ {
+ /* Get base from parameter list */
+ base = (int)parameters[base].data.number.as_signed;
+ }
+
+ switch (parameters[i].type)
+ {
+ case FORMAT_CHAR:
+ if (flags & FLAGS_QUOTE)
+ data->OutStream(data, CHAR_QUOTE);
+ if (! (flags & FLAGS_LEFTADJUST))
+ {
+ while (--width > 0)
+ data->OutStream(data, CHAR_ADJUST);
+ }
+#if TRIO_WIDECHAR
+ if (flags & FLAGS_WIDECHAR)
+ {
+ TrioWriteWideStringCharacter(data,
+ (trio_wchar_t)parameters[i].data.number.as_signed,
+ flags,
+ NO_WIDTH);
+ }
+ else
+#endif
+ {
+ TrioWriteStringCharacter(data,
+ (int)parameters[i].data.number.as_signed,
+ flags);
+ }
+
+ if (flags & FLAGS_LEFTADJUST)
+ {
+ while(--width > 0)
+ data->OutStream(data, CHAR_ADJUST);
+ }
+ if (flags & FLAGS_QUOTE)
+ data->OutStream(data, CHAR_QUOTE);
+
+ break; /* FORMAT_CHAR */
+
+ case FORMAT_INT:
+ TrioWriteNumber(data,
+ parameters[i].data.number.as_unsigned,
+ flags,
+ width,
+ precision,
+ base);
+
+ break; /* FORMAT_INT */
+
+ case FORMAT_DOUBLE:
+ TrioWriteDouble(data,
+ parameters[i].data.longdoubleNumber,
+ flags,
+ width,
+ precision,
+ base);
+ break; /* FORMAT_DOUBLE */
+
+ case FORMAT_STRING:
+#if TRIO_WIDECHAR
+ if (flags & FLAGS_WIDECHAR)
+ {
+ TrioWriteWideString(data,
+ parameters[i].data.wstring,
+ flags,
+ width,
+ precision);
+ }
+ else
+#endif
+ {
+ TrioWriteString(data,
+ parameters[i].data.string,
+ flags,
+ width,
+ precision);
+ }
+ break; /* FORMAT_STRING */
+
+ case FORMAT_POINTER:
+ {
+ trio_reference_t reference;
+
+ reference.data = data;
+ reference.parameter = &parameters[i];
+ trio_print_pointer(&reference, parameters[i].data.pointer);
+ }
+ break; /* FORMAT_POINTER */
+
+ case FORMAT_COUNT:
+ pointer = parameters[i].data.pointer;
+ if (NULL != pointer)
+ {
+ /*
+ * C99 paragraph 7.19.6.1.8 says "the number of
+ * characters written to the output stream so far by
+ * this call", which is data->committed
+ */
+#if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
+ if (flags & FLAGS_SIZE_T)
+ *(size_t *)pointer = (size_t)data->committed;
+ else
+#endif
+#if defined(QUALIFIER_PTRDIFF_T)
+ if (flags & FLAGS_PTRDIFF_T)
+ *(ptrdiff_t *)pointer = (ptrdiff_t)data->committed;
+ else
+#endif
+#if defined(QUALIFIER_INTMAX_T)
+ if (flags & FLAGS_INTMAX_T)
+ *(trio_intmax_t *)pointer = (trio_intmax_t)data->committed;
+ else
+#endif
+ if (flags & FLAGS_QUAD)
+ {
+ *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)data->committed;
+ }
+ else if (flags & FLAGS_LONG)
+ {
+ *(long int *)pointer = (long int)data->committed;
+ }
+ else if (flags & FLAGS_SHORT)
+ {
+ *(short int *)pointer = (short int)data->committed;
+ }
+ else
+ {
+ *(int *)pointer = (int)data->committed;
+ }
+ }
+ break; /* FORMAT_COUNT */
+
+ case FORMAT_PARAMETER:
+ break; /* FORMAT_PARAMETER */
+
+#if defined(FORMAT_ERRNO)
+ case FORMAT_ERRNO:
+ string = trio_error(parameters[i].data.errorNumber);
+ if (string)
+ {
+ TrioWriteString(data,
+ string,
+ flags,
+ width,
+ precision);
+ }
+ else
+ {
+ data->OutStream(data, '#');
+ TrioWriteNumber(data,
+ (trio_uintmax_t)parameters[i].data.errorNumber,
+ flags,
+ width,
+ precision,
+ BASE_DECIMAL);
+ }
+ break; /* FORMAT_ERRNO */
+#endif /* defined(FORMAT_ERRNO) */
+
+#if defined(FORMAT_USER_DEFINED)
+ case FORMAT_USER_DEFINED:
+ {
+ trio_reference_t reference;
+ trio_userdef_t *def = NULL;
+
+ if (parameters[i].user_name[0] == NIL)
+ {
+ /* Use handle */
+ if ((i > 0) ||
+ (parameters[i - 1].type == FORMAT_PARAMETER))
+ def = (trio_userdef_t *)parameters[i - 1].data.pointer;
+ }
+ else
+ {
+ /* Look up namespace */
+ def = TrioFindNamespace(parameters[i].user_name, NULL);
+ }
+ if (def) {
+ reference.data = data;
+ reference.parameter = &parameters[i];
+ def->callback(&reference);
+ }
+ }
+ break;
+#endif /* defined(FORMAT_USER_DEFINED) */
+
+ default:
+ break;
+ } /* switch parameter type */
+
+ /* Prepare for next */
+ index = parameters[i].indexAfterSpecifier;
+ i++;
+ }
+ }
+ else /* not identifier */
+ {
+ data->OutStream(data, format[index++]);
+ }
+ }
+ return data->processed;
+}
+
+/*************************************************************************
+ * TrioFormatRef
+ */
+TRIO_PRIVATE int
+TrioFormatRef
+TRIO_ARGS4((reference, format, arglist, argarray),
+ trio_reference_t *reference,
+ TRIO_CONST char *format,
+ va_list *arglist,
+ trio_pointer_t *argarray)
+{
+ int status;
+ trio_parameter_t parameters[MAX_PARAMETERS];
+
+ status = TrioParse(TYPE_PRINT, format, parameters, arglist, argarray);
+ if (status < 0)
+ return status;
+
+ status = TrioFormatProcess(reference->data, format, parameters);
+ if (reference->data->error != 0)
+ {
+ status = reference->data->error;
+ }
+ return status;
+}
+
+/*************************************************************************
+ * TrioFormat
+ */
+TRIO_PRIVATE int
+TrioFormat
+TRIO_ARGS6((destination, destinationSize, OutStream, format, arglist, argarray),
+ trio_pointer_t destination,
+ size_t destinationSize,
+ void (*OutStream) TRIO_PROTO((trio_class_t *, int)),
+ TRIO_CONST char *format,
+ va_list *arglist,
+ trio_pointer_t *argarray)
+{
+ int status;
+ trio_class_t data;
+ trio_parameter_t parameters[MAX_PARAMETERS];
+
+ assert(VALID(OutStream));
+ assert(VALID(format));
+
+ memset(&data, 0, sizeof(data));
+ data.OutStream = OutStream;
+ data.location = destination;
+ data.max = destinationSize;
+ data.error = 0;
+
+#if defined(USE_LOCALE)
+ if (NULL == internalLocaleValues)
+ {
+ TrioSetLocale();
+ }
+#endif
+
+ status = TrioParse(TYPE_PRINT, format, parameters, arglist, argarray);
+ if (status < 0)
+ return status;
+
+ status = TrioFormatProcess(&data, format, parameters);
+ if (data.error != 0)
+ {
+ status = data.error;
+ }
+ return status;
+}
+
+/*************************************************************************
+ * TrioOutStreamFile
+ */
+TRIO_PRIVATE void
+TrioOutStreamFile
+TRIO_ARGS2((self, output),
+ trio_class_t *self,
+ int output)
+{
+ FILE *file;
+
+ assert(VALID(self));
+ assert(VALID(self->location));
+
+ file = (FILE *)self->location;
+ self->processed++;
+ if (fputc(output, file) == EOF)
+ {
+ self->error = TRIO_ERROR_RETURN(TRIO_EOF, 0);
+ }
+ else
+ {
+ self->committed++;
+ }
+}
+
+/*************************************************************************
+ * TrioOutStreamFileDescriptor
+ */
+TRIO_PRIVATE void
+TrioOutStreamFileDescriptor
+TRIO_ARGS2((self, output),
+ trio_class_t *self,
+ int output)
+{
+ int fd;
+ char ch;
+
+ assert(VALID(self));
+
+ fd = *((int *)self->location);
+ ch = (char)output;
+ self->processed++;
+ if (write(fd, &ch, sizeof(char)) == -1)
+ {
+ self->error = TRIO_ERROR_RETURN(TRIO_ERRNO, 0);
+ }
+ else
+ {
+ self->committed++;
+ }
+}
+
+/*************************************************************************
+ * TrioOutStreamCustom
+ */
+TRIO_PRIVATE void
+TrioOutStreamCustom
+TRIO_ARGS2((self, output),
+ trio_class_t *self,
+ int output)
+{
+ int status;
+ trio_custom_t *data;
+
+ assert(VALID(self));
+ assert(VALID(self->location));
+
+ data = (trio_custom_t *)self->location;
+ if (data->stream.out)
+ {
+ status = (data->stream.out)(data->closure, output);
+ if (status >= 0)
+ {
+ self->committed++;
+ }
+ else
+ {
+ if (self->error == 0)
+ {
+ self->error = TRIO_ERROR_RETURN(TRIO_ECUSTOM, -status);
+ }
+ }
+ }
+ self->processed++;
+}
+
+/*************************************************************************
+ * TrioOutStreamString
+ */
+TRIO_PRIVATE void
+TrioOutStreamString
+TRIO_ARGS2((self, output),
+ trio_class_t *self,
+ int output)
+{
+ char **buffer;
+
+ assert(VALID(self));
+ assert(VALID(self->location));
+
+ buffer = (char **)self->location;
+ **buffer = (char)output;
+ (*buffer)++;
+ self->processed++;
+ self->committed++;
+}
+
+/*************************************************************************
+ * TrioOutStreamStringMax
+ */
+TRIO_PRIVATE void
+TrioOutStreamStringMax
+TRIO_ARGS2((self, output),
+ trio_class_t *self,
+ int output)
+{
+ char **buffer;
+
+ assert(VALID(self));
+ assert(VALID(self->location));
+
+ buffer = (char **)self->location;
+
+ if (self->processed < self->max)
+ {
+ **buffer = (char)output;
+ (*buffer)++;
+ self->committed++;
+ }
+ self->processed++;
+}
+
+/*************************************************************************
+ * TrioOutStreamStringDynamic
+ */
+TRIO_PRIVATE void
+TrioOutStreamStringDynamic
+TRIO_ARGS2((self, output),
+ trio_class_t *self,
+ int output)
+{
+ assert(VALID(self));
+ assert(VALID(self->location));
+
+ if (self->error == 0)
+ {
+ trio_xstring_append_char((trio_string_t *)self->location,
+ (char)output);
+ self->committed++;
+ }
+ /* The processed variable must always be increased */
+ self->processed++;
+}
+
+/*************************************************************************
+ *
+ * Formatted printing functions
+ *
+ ************************************************************************/
+
+#if defined(TRIO_DOCUMENTATION)
+# include "doc/doc_printf.h"
+#endif
+/** @addtogroup Printf
+ @{
+*/
+
+/*************************************************************************
+ * printf
+ */
+
+/**
+ Print to standard output stream.
+
+ @param format Formatting string.
+ @param ... Arguments.
+ @return Number of printed characters.
+ */
+TRIO_PUBLIC int
+trio_printf
+TRIO_VARGS2((format, va_alist),
+ TRIO_CONST char *format,
+ TRIO_VA_DECL)
+{
+ int status;
+ va_list args;
+
+ assert(VALID(format));
+
+ TRIO_VA_START(args, format);
+ status = TrioFormat(stdout, 0, TrioOutStreamFile, format, &args, NULL);
+ TRIO_VA_END(args);
+ return status;
+}
+
+/**
+ Print to standard output stream.
+
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of printed characters.
+ */
+TRIO_PUBLIC int
+trio_vprintf
+TRIO_ARGS2((format, args),
+ TRIO_CONST char *format,
+ va_list args)
+{
+ assert(VALID(format));
+
+ return TrioFormat(stdout, 0, TrioOutStreamFile, format, &args, NULL);
+}
+
+/**
+ Print to standard output stream.
+
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of printed characters.
+ */
+TRIO_PUBLIC int
+trio_printfv
+TRIO_ARGS2((format, args),
+ TRIO_CONST char *format,
+ trio_pointer_t * args)
+{
+ assert(VALID(format));
+
+ return TrioFormat(stdout, 0, TrioOutStreamFile, format, NULL, args);
+}
+
+/*************************************************************************
+ * fprintf
+ */
+
+/**
+ Print to file.
+
+ @param file File pointer.
+ @param format Formatting string.
+ @param ... Arguments.
+ @return Number of printed characters.
+ */
+TRIO_PUBLIC int
+trio_fprintf
+TRIO_VARGS3((file, format, va_alist),
+ FILE *file,
+ TRIO_CONST char *format,
+ TRIO_VA_DECL)
+{
+ int status;
+ va_list args;
+
+ assert(VALID(file));
+ assert(VALID(format));
+
+ TRIO_VA_START(args, format);
+ status = TrioFormat(file, 0, TrioOutStreamFile, format, &args, NULL);
+ TRIO_VA_END(args);
+ return status;
+}
+
+/**
+ Print to file.
+
+ @param file File pointer.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of printed characters.
+ */
+TRIO_PUBLIC int
+trio_vfprintf
+TRIO_ARGS3((file, format, args),
+ FILE *file,
+ TRIO_CONST char *format,
+ va_list args)
+{
+ assert(VALID(file));
+ assert(VALID(format));
+
+ return TrioFormat(file, 0, TrioOutStreamFile, format, &args, NULL);
+}
+
+/**
+ Print to file.
+
+ @param file File pointer.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of printed characters.
+ */
+TRIO_PUBLIC int
+trio_fprintfv
+TRIO_ARGS3((file, format, args),
+ FILE *file,
+ TRIO_CONST char *format,
+ trio_pointer_t * args)
+{
+ assert(VALID(file));
+ assert(VALID(format));
+
+ return TrioFormat(file, 0, TrioOutStreamFile, format, NULL, args);
+}
+
+/*************************************************************************
+ * dprintf
+ */
+
+/**
+ Print to file descriptor.
+
+ @param fd File descriptor.
+ @param format Formatting string.
+ @param ... Arguments.
+ @return Number of printed characters.
+ */
+TRIO_PUBLIC int
+trio_dprintf
+TRIO_VARGS3((fd, format, va_alist),
+ int fd,
+ TRIO_CONST char *format,
+ TRIO_VA_DECL)
+{
+ int status;
+ va_list args;
+
+ assert(VALID(format));
+
+ TRIO_VA_START(args, format);
+ status = TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, &args, NULL);
+ TRIO_VA_END(args);
+ return status;
+}
+
+/**
+ Print to file descriptor.
+
+ @param fd File descriptor.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of printed characters.
+ */
+TRIO_PUBLIC int
+trio_vdprintf
+TRIO_ARGS3((fd, format, args),
+ int fd,
+ TRIO_CONST char *format,
+ va_list args)
+{
+ assert(VALID(format));
+
+ return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, &args, NULL);
+}
+
+/**
+ Print to file descriptor.
+
+ @param fd File descriptor.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of printed characters.
+ */
+TRIO_PUBLIC int
+trio_dprintfv
+TRIO_ARGS3((fd, format, args),
+ int fd,
+ TRIO_CONST char *format,
+ trio_pointer_t *args)
+{
+ assert(VALID(format));
+
+ return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, NULL, args);
+}
+
+/*************************************************************************
+ * cprintf
+ */
+TRIO_PUBLIC int
+trio_cprintf
+TRIO_VARGS4((stream, closure, format, va_alist),
+ trio_outstream_t stream,
+ trio_pointer_t closure,
+ TRIO_CONST char *format,
+ TRIO_VA_DECL)
+{
+ int status;
+ va_list args;
+ trio_custom_t data;
+
+ assert(VALID(stream));
+ assert(VALID(format));
+
+ TRIO_VA_START(args, format);
+ data.stream.out = stream;
+ data.closure = closure;
+ status = TrioFormat(&data, 0, TrioOutStreamCustom, format, &args, NULL);
+ TRIO_VA_END(args);
+ return status;
+}
+
+TRIO_PUBLIC int
+trio_vcprintf
+TRIO_ARGS4((stream, closure, format, args),
+ trio_outstream_t stream,
+ trio_pointer_t closure,
+ TRIO_CONST char *format,
+ va_list args)
+{
+ trio_custom_t data;
+
+ assert(VALID(stream));
+ assert(VALID(format));
+
+ data.stream.out = stream;
+ data.closure = closure;
+ return TrioFormat(&data, 0, TrioOutStreamCustom, format, &args, NULL);
+}
+
+TRIO_PUBLIC int
+trio_cprintfv
+TRIO_ARGS4((stream, closure, format, args),
+ trio_outstream_t stream,
+ trio_pointer_t closure,
+ TRIO_CONST char *format,
+ void **args)
+{
+ trio_custom_t data;
+
+ assert(VALID(stream));
+ assert(VALID(format));
+
+ data.stream.out = stream;
+ data.closure = closure;
+ return TrioFormat(&data, 0, TrioOutStreamCustom, format, NULL, args);
+}
+
+/*************************************************************************
+ * sprintf
+ */
+
+/**
+ Print to string.
+
+ @param buffer Output string.
+ @param format Formatting string.
+ @param ... Arguments.
+ @return Number of printed characters.
+ */
+TRIO_PUBLIC int
+trio_sprintf
+TRIO_VARGS3((buffer, format, va_alist),
+ char *buffer,
+ TRIO_CONST char *format,
+ TRIO_VA_DECL)
+{
+ int status;
+ va_list args;
+
+ assert(VALID(buffer));
+ assert(VALID(format));
+
+ TRIO_VA_START(args, format);
+ status = TrioFormat(&buffer, 0, TrioOutStreamString, format, &args, NULL);
+ *buffer = NIL; /* Terminate with NIL character */
+ TRIO_VA_END(args);
+ return status;
+}
+
+/**
+ Print to string.
+
+ @param buffer Output string.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of printed characters.
+ */
+TRIO_PUBLIC int
+trio_vsprintf
+TRIO_ARGS3((buffer, format, args),
+ char *buffer,
+ TRIO_CONST char *format,
+ va_list args)
+{
+ int status;
+
+ assert(VALID(buffer));
+ assert(VALID(format));
+
+ status = TrioFormat(&buffer, 0, TrioOutStreamString, format, &args, NULL);
+ *buffer = NIL;
+ return status;
+}
+
+/**
+ Print to string.
+
+ @param buffer Output string.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of printed characters.
+ */
+TRIO_PUBLIC int
+trio_sprintfv
+TRIO_ARGS3((buffer, format, args),
+ char *buffer,
+ TRIO_CONST char *format,
+ trio_pointer_t *args)
+{
+ int status;
+
+ assert(VALID(buffer));
+ assert(VALID(format));
+
+ status = TrioFormat(&buffer, 0, TrioOutStreamString, format, NULL, args);
+ *buffer = NIL;
+ return status;
+}
+
+/*************************************************************************
+ * snprintf
+ */
+
+/**
+ Print at most @p max characters to string.
+
+ @param buffer Output string.
+ @param max Maximum number of characters to print.
+ @param format Formatting string.
+ @param ... Arguments.
+ @return Number of printed characters.
+ */
+TRIO_PUBLIC int
+trio_snprintf
+TRIO_VARGS4((buffer, max, format, va_alist),
+ char *buffer,
+ size_t max,
+ TRIO_CONST char *format,
+ TRIO_VA_DECL)
+{
+ int status;
+ va_list args;
+
+ assert(VALID(buffer));
+ assert(VALID(format));
+
+ TRIO_VA_START(args, format);
+ status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
+ TrioOutStreamStringMax, format, &args, NULL);
+ if (max > 0)
+ *buffer = NIL;
+ TRIO_VA_END(args);
+ return status;
+}
+
+/**
+ Print at most @p max characters to string.
+
+ @param buffer Output string.
+ @param max Maximum number of characters to print.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of printed characters.
+ */
+TRIO_PUBLIC int
+trio_vsnprintf
+TRIO_ARGS4((buffer, max, format, args),
+ char *buffer,
+ size_t max,
+ TRIO_CONST char *format,
+ va_list args)
+{
+ int status;
+
+ assert(VALID(buffer));
+ assert(VALID(format));
+
+ status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
+ TrioOutStreamStringMax, format, &args, NULL);
+ if (max > 0)
+ *buffer = NIL;
+ return status;
+}
+
+/**
+ Print at most @p max characters to string.
+
+ @param buffer Output string.
+ @param max Maximum number of characters to print.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of printed characters.
+ */
+TRIO_PUBLIC int
+trio_snprintfv
+TRIO_ARGS4((buffer, max, format, args),
+ char *buffer,
+ size_t max,
+ TRIO_CONST char *format,
+ trio_pointer_t *args)
+{
+ int status;
+
+ assert(VALID(buffer));
+ assert(VALID(format));
+
+ status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
+ TrioOutStreamStringMax, format, NULL, args);
+ if (max > 0)
+ *buffer = NIL;
+ return status;
+}
+
+/*************************************************************************
+ * snprintfcat
+ * Appends the new string to the buffer string overwriting the '\0'
+ * character at the end of buffer.
+ */
+TRIO_PUBLIC int
+trio_snprintfcat
+TRIO_VARGS4((buffer, max, format, va_alist),
+ char *buffer,
+ size_t max,
+ TRIO_CONST char *format,
+ TRIO_VA_DECL)
+{
+ int status;
+ va_list args;
+ size_t buf_len;
+
+ TRIO_VA_START(args, format);
+
+ assert(VALID(buffer));
+ assert(VALID(format));
+
+ buf_len = trio_length(buffer);
+ buffer = &buffer[buf_len];
+
+ status = TrioFormat(&buffer, max - 1 - buf_len,
+ TrioOutStreamStringMax, format, &args, NULL);
+ TRIO_VA_END(args);
+ *buffer = NIL;
+ return status;
+}
+
+TRIO_PUBLIC int
+trio_vsnprintfcat
+TRIO_ARGS4((buffer, max, format, args),
+ char *buffer,
+ size_t max,
+ TRIO_CONST char *format,
+ va_list args)
+{
+ int status;
+ size_t buf_len;
+
+ assert(VALID(buffer));
+ assert(VALID(format));
+
+ buf_len = trio_length(buffer);
+ buffer = &buffer[buf_len];
+ status = TrioFormat(&buffer, max - 1 - buf_len,
+ TrioOutStreamStringMax, format, &args, NULL);
+ *buffer = NIL;
+ return status;
+}
+
+/*************************************************************************
+ * trio_aprintf
+ */
+
+/* Deprecated */
+TRIO_PUBLIC char *
+trio_aprintf
+TRIO_VARGS2((format, va_alist),
+ TRIO_CONST char *format,
+ TRIO_VA_DECL)
+{
+ va_list args;
+ trio_string_t *info;
+ char *result = NULL;
+
+ assert(VALID(format));
+
+ info = trio_xstring_duplicate("");
+ if (info)
+ {
+ TRIO_VA_START(args, format);
+ (void)TrioFormat(info, 0, TrioOutStreamStringDynamic,
+ format, &args, NULL);
+ TRIO_VA_END(args);
+
+ trio_string_terminate(info);
+ result = trio_string_extract(info);
+ trio_string_destroy(info);
+ }
+ return result;
+}
+
+/* Deprecated */
+TRIO_PUBLIC char *
+trio_vaprintf
+TRIO_ARGS2((format, args),
+ TRIO_CONST char *format,
+ va_list args)
+{
+ trio_string_t *info;
+ char *result = NULL;
+
+ assert(VALID(format));
+
+ info = trio_xstring_duplicate("");
+ if (info)
+ {
+ (void)TrioFormat(info, 0, TrioOutStreamStringDynamic,
+ format, &args, NULL);
+ trio_string_terminate(info);
+ result = trio_string_extract(info);
+ trio_string_destroy(info);
+ }
+ return result;
+}
+
+TRIO_PUBLIC int
+trio_asprintf
+TRIO_VARGS3((result, format, va_alist),
+ char **result,
+ TRIO_CONST char *format,
+ TRIO_VA_DECL)
+{
+ va_list args;
+ int status;
+ trio_string_t *info;
+
+ assert(VALID(format));
+
+ *result = NULL;
+
+ info = trio_xstring_duplicate("");
+ if (info == NULL)
+ {
+ status = TRIO_ERROR_RETURN(TRIO_ENOMEM, 0);
+ }
+ else
+ {
+ TRIO_VA_START(args, format);
+ status = TrioFormat(info, 0, TrioOutStreamStringDynamic,
+ format, &args, NULL);
+ TRIO_VA_END(args);
+ if (status >= 0)
+ {
+ trio_string_terminate(info);
+ *result = trio_string_extract(info);
+ }
+ trio_string_destroy(info);
+ }
+ return status;
+}
+
+TRIO_PUBLIC int
+trio_vasprintf
+TRIO_ARGS3((result, format, args),
+ char **result,
+ TRIO_CONST char *format,
+ va_list args)
+{
+ int status;
+ trio_string_t *info;
+
+ assert(VALID(format));
+
+ *result = NULL;
+
+ info = trio_xstring_duplicate("");
+ if (info == NULL)
+ {
+ status = TRIO_ERROR_RETURN(TRIO_ENOMEM, 0);
+ }
+ else
+ {
+ status = TrioFormat(info, 0, TrioOutStreamStringDynamic,
+ format, &args, NULL);
+ if (status >= 0)
+ {
+ trio_string_terminate(info);
+ *result = trio_string_extract(info);
+ }
+ trio_string_destroy(info);
+ }
+ return status;
+}
+
+/** @} End of Printf documentation module */
+
+/*************************************************************************
+ *
+ * CALLBACK
+ *
+ ************************************************************************/
+
+#if defined(TRIO_DOCUMENTATION)
+# include "doc/doc_register.h"
+#endif
+/**
+ @addtogroup UserDefined
+ @{
+*/
+
+#if TRIO_EXTENSION
+
+/*************************************************************************
+ * trio_register
+ */
+
+/**
+ Register new user-defined specifier.
+
+ @param callback
+ @param name
+ @return Handle.
+ */
+TRIO_PUBLIC trio_pointer_t
+trio_register
+TRIO_ARGS2((callback, name),
+ trio_callback_t callback,
+ TRIO_CONST char *name)
+{
+ trio_userdef_t *def;
+ trio_userdef_t *prev = NULL;
+
+ if (callback == NULL)
+ return NULL;
+
+ if (name)
+ {
+ /* Handle built-in namespaces */
+ if (name[0] == ':')
+ {
+ if (trio_equal(name, ":enter"))
+ {
+ internalEnterCriticalRegion = callback;
+ }
+ else if (trio_equal(name, ":leave"))
+ {
+ internalLeaveCriticalRegion = callback;
+ }
+ return NULL;
+ }
+
+ /* Bail out if namespace is too long */
+ if (trio_length(name) >= MAX_USER_NAME)
+ return NULL;
+
+ /* Bail out if namespace already is registered */
+ def = TrioFindNamespace(name, &prev);
+ if (def)
+ return NULL;
+ }
+
+ def = (trio_userdef_t *)TRIO_MALLOC(sizeof(trio_userdef_t));
+ if (def)
+ {
+ if (internalEnterCriticalRegion)
+ (void)internalEnterCriticalRegion(NULL);
+
+ if (name)
+ {
+ /* Link into internal list */
+ if (prev == NULL)
+ internalUserDef = def;
+ else
+ prev->next = def;
+ }
+ /* Initialize */
+ def->callback = callback;
+ def->name = (name == NULL)
+ ? NULL
+ : trio_duplicate(name);
+ def->next = NULL;
+
+ if (internalLeaveCriticalRegion)
+ (void)internalLeaveCriticalRegion(NULL);
+ }
+ return (trio_pointer_t)def;
+}
+
+/**
+ Unregister an existing user-defined specifier.
+
+ @param handle
+ */
+void
+trio_unregister
+TRIO_ARGS1((handle),
+ trio_pointer_t handle)
+{
+ trio_userdef_t *self = (trio_userdef_t *)handle;
+ trio_userdef_t *def;
+ trio_userdef_t *prev = NULL;
+
+ assert(VALID(self));
+
+ if (self->name)
+ {
+ def = TrioFindNamespace(self->name, &prev);
+ if (def)
+ {
+ if (internalEnterCriticalRegion)
+ (void)internalEnterCriticalRegion(NULL);
+
+ if (prev == NULL)
+ internalUserDef = NULL;
+ else
+ prev->next = def->next;
+
+ if (internalLeaveCriticalRegion)
+ (void)internalLeaveCriticalRegion(NULL);
+ }
+ trio_destroy(self->name);
+ }
+ TRIO_FREE(self);
+}
+
+/*************************************************************************
+ * trio_get_format [public]
+ */
+TRIO_CONST char *
+trio_get_format
+TRIO_ARGS1((ref),
+ trio_pointer_t ref)
+{
+#if defined(FORMAT_USER_DEFINED)
+ assert(((trio_reference_t *)ref)->parameter->type == FORMAT_USER_DEFINED);
+#endif
+
+ return (((trio_reference_t *)ref)->parameter->user_data);
+}
+
+/*************************************************************************
+ * trio_get_argument [public]
+ */
+trio_pointer_t
+trio_get_argument
+TRIO_ARGS1((ref),
+ trio_pointer_t ref)
+{
+#if defined(FORMAT_USER_DEFINED)
+ assert(((trio_reference_t *)ref)->parameter->type == FORMAT_USER_DEFINED);
+#endif
+
+ return ((trio_reference_t *)ref)->parameter->data.pointer;
+}
+
+/*************************************************************************
+ * trio_get_width / trio_set_width [public]
+ */
+int
+trio_get_width
+TRIO_ARGS1((ref),
+ trio_pointer_t ref)
+{
+ return ((trio_reference_t *)ref)->parameter->width;
+}
+
+void
+trio_set_width
+TRIO_ARGS2((ref, width),
+ trio_pointer_t ref,
+ int width)
+{
+ ((trio_reference_t *)ref)->parameter->width = width;
+}
+
+/*************************************************************************
+ * trio_get_precision / trio_set_precision [public]
+ */
+int
+trio_get_precision
+TRIO_ARGS1((ref),
+ trio_pointer_t ref)
+{
+ return (((trio_reference_t *)ref)->parameter->precision);
+}
+
+void
+trio_set_precision
+TRIO_ARGS2((ref, precision),
+ trio_pointer_t ref,
+ int precision)
+{
+ ((trio_reference_t *)ref)->parameter->precision = precision;
+}
+
+/*************************************************************************
+ * trio_get_base / trio_set_base [public]
+ */
+int
+trio_get_base
+TRIO_ARGS1((ref),
+ trio_pointer_t ref)
+{
+ return (((trio_reference_t *)ref)->parameter->base);
+}
+
+void
+trio_set_base
+TRIO_ARGS2((ref, base),
+ trio_pointer_t ref,
+ int base)
+{
+ ((trio_reference_t *)ref)->parameter->base = base;
+}
+
+/*************************************************************************
+ * trio_get_long / trio_set_long [public]
+ */
+int
+trio_get_long
+TRIO_ARGS1((ref),
+ trio_pointer_t ref)
+{
+ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LONG)
+ ? TRUE
+ : FALSE;
+}
+
+void
+trio_set_long
+TRIO_ARGS2((ref, is_long),
+ trio_pointer_t ref,
+ int is_long)
+{
+ if (is_long)
+ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LONG;
+ else
+ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LONG;
+}
+
+/*************************************************************************
+ * trio_get_longlong / trio_set_longlong [public]
+ */
+int
+trio_get_longlong
+TRIO_ARGS1((ref),
+ trio_pointer_t ref)
+{
+ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_QUAD)
+ ? TRUE
+ : FALSE;
+}
+
+void
+trio_set_longlong
+TRIO_ARGS2((ref, is_longlong),
+ trio_pointer_t ref,
+ int is_longlong)
+{
+ if (is_longlong)
+ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_QUAD;
+ else
+ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_QUAD;
+}
+
+/*************************************************************************
+ * trio_get_longdouble / trio_set_longdouble [public]
+ */
+int
+trio_get_longdouble
+TRIO_ARGS1((ref),
+ trio_pointer_t ref)
+{
+ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LONGDOUBLE)
+ ? TRUE
+ : FALSE;
+}
+
+void
+trio_set_longdouble
+TRIO_ARGS2((ref, is_longdouble),
+ trio_pointer_t ref,
+ int is_longdouble)
+{
+ if (is_longdouble)
+ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LONGDOUBLE;
+ else
+ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LONGDOUBLE;
+}
+
+/*************************************************************************
+ * trio_get_short / trio_set_short [public]
+ */
+int
+trio_get_short
+TRIO_ARGS1((ref),
+ trio_pointer_t ref)
+{
+ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHORT)
+ ? TRUE
+ : FALSE;
+}
+
+void
+trio_set_short
+TRIO_ARGS2((ref, is_short),
+ trio_pointer_t ref,
+ int is_short)
+{
+ if (is_short)
+ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHORT;
+ else
+ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHORT;
+}
+
+/*************************************************************************
+ * trio_get_shortshort / trio_set_shortshort [public]
+ */
+int
+trio_get_shortshort
+TRIO_ARGS1((ref),
+ trio_pointer_t ref)
+{
+ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHORTSHORT)
+ ? TRUE
+ : FALSE;
+}
+
+void
+trio_set_shortshort
+TRIO_ARGS2((ref, is_shortshort),
+ trio_pointer_t ref,
+ int is_shortshort)
+{
+ if (is_shortshort)
+ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHORTSHORT;
+ else
+ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHORTSHORT;
+}
+
+/*************************************************************************
+ * trio_get_alternative / trio_set_alternative [public]
+ */
+int
+trio_get_alternative
+TRIO_ARGS1((ref),
+ trio_pointer_t ref)
+{
+ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_ALTERNATIVE)
+ ? TRUE
+ : FALSE;
+}
+
+void
+trio_set_alternative
+TRIO_ARGS2((ref, is_alternative),
+ trio_pointer_t ref,
+ int is_alternative)
+{
+ if (is_alternative)
+ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_ALTERNATIVE;
+ else
+ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_ALTERNATIVE;
+}
+
+/*************************************************************************
+ * trio_get_alignment / trio_set_alignment [public]
+ */
+int
+trio_get_alignment
+TRIO_ARGS1((ref),
+ trio_pointer_t ref)
+{
+ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LEFTADJUST)
+ ? TRUE
+ : FALSE;
+}
+
+void
+trio_set_alignment
+TRIO_ARGS2((ref, is_leftaligned),
+ trio_pointer_t ref,
+ int is_leftaligned)
+{
+ if (is_leftaligned)
+ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LEFTADJUST;
+ else
+ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LEFTADJUST;
+}
+
+/*************************************************************************
+ * trio_get_spacing /trio_set_spacing [public]
+ */
+int
+trio_get_spacing
+TRIO_ARGS1((ref),
+ trio_pointer_t ref)
+{
+ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SPACE)
+ ? TRUE
+ : FALSE;
+}
+
+void
+trio_set_spacing
+TRIO_ARGS2((ref, is_space),
+ trio_pointer_t ref,
+ int is_space)
+{
+ if (is_space)
+ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SPACE;
+ else
+ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SPACE;
+}
+
+/*************************************************************************
+ * trio_get_sign / trio_set_sign [public]
+ */
+int
+trio_get_sign
+TRIO_ARGS1((ref),
+ trio_pointer_t ref)
+{
+ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHOWSIGN)
+ ? TRUE
+ : FALSE;
+}
+
+void
+trio_set_sign
+TRIO_ARGS2((ref, is_sign),
+ trio_pointer_t ref,
+ int is_sign)
+{
+ if (is_sign)
+ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHOWSIGN;
+ else
+ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHOWSIGN;
+}
+
+/*************************************************************************
+ * trio_get_padding / trio_set_padding [public]
+ */
+int
+trio_get_padding
+TRIO_ARGS1((ref),
+ trio_pointer_t ref)
+{
+ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_NILPADDING)
+ ? TRUE
+ : FALSE;
+}
+
+void
+trio_set_padding
+TRIO_ARGS2((ref, is_padding),
+ trio_pointer_t ref,
+ int is_padding)
+{
+ if (is_padding)
+ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_NILPADDING;
+ else
+ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_NILPADDING;
+}
+
+/*************************************************************************
+ * trio_get_quote / trio_set_quote [public]
+ */
+int
+trio_get_quote
+TRIO_ARGS1((ref),
+ trio_pointer_t ref)
+{
+ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_QUOTE)
+ ? TRUE
+ : FALSE;
+}
+
+void
+trio_set_quote
+TRIO_ARGS2((ref, is_quote),
+ trio_pointer_t ref,
+ int is_quote)
+{
+ if (is_quote)
+ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_QUOTE;
+ else
+ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_QUOTE;
+}
+
+/*************************************************************************
+ * trio_get_upper / trio_set_upper [public]
+ */
+int
+trio_get_upper
+TRIO_ARGS1((ref),
+ trio_pointer_t ref)
+{
+ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_UPPER)
+ ? TRUE
+ : FALSE;
+}
+
+void
+trio_set_upper
+TRIO_ARGS2((ref, is_upper),
+ trio_pointer_t ref,
+ int is_upper)
+{
+ if (is_upper)
+ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_UPPER;
+ else
+ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_UPPER;
+}
+
+/*************************************************************************
+ * trio_get_largest / trio_set_largest [public]
+ */
+#if TRIO_C99
+int
+trio_get_largest
+TRIO_ARGS1((ref),
+ trio_pointer_t ref)
+{
+ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_INTMAX_T)
+ ? TRUE
+ : FALSE;
+}
+
+void
+trio_set_largest
+TRIO_ARGS2((ref, is_largest),
+ trio_pointer_t ref,
+ int is_largest)
+{
+ if (is_largest)
+ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_INTMAX_T;
+ else
+ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_INTMAX_T;
+}
+#endif
+
+/*************************************************************************
+ * trio_get_ptrdiff / trio_set_ptrdiff [public]
+ */
+int
+trio_get_ptrdiff
+TRIO_ARGS1((ref),
+ trio_pointer_t ref)
+{
+ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_PTRDIFF_T)
+ ? TRUE
+ : FALSE;
+}
+
+void
+trio_set_ptrdiff
+TRIO_ARGS2((ref, is_ptrdiff),
+ trio_pointer_t ref,
+ int is_ptrdiff)
+{
+ if (is_ptrdiff)
+ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_PTRDIFF_T;
+ else
+ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_PTRDIFF_T;
+}
+
+/*************************************************************************
+ * trio_get_size / trio_set_size [public]
+ */
+#if TRIO_C99
+int
+trio_get_size
+TRIO_ARGS1((ref),
+ trio_pointer_t ref)
+{
+ return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SIZE_T)
+ ? TRUE
+ : FALSE;
+}
+
+void
+trio_set_size
+TRIO_ARGS2((ref, is_size),
+ trio_pointer_t ref,
+ int is_size)
+{
+ if (is_size)
+ ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SIZE_T;
+ else
+ ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SIZE_T;
+}
+#endif
+
+/*************************************************************************
+ * trio_print_int [public]
+ */
+void
+trio_print_int
+TRIO_ARGS2((ref, number),
+ trio_pointer_t ref,
+ int number)
+{
+ trio_reference_t *self = (trio_reference_t *)ref;
+
+ TrioWriteNumber(self->data,
+ (trio_uintmax_t)number,
+ self->parameter->flags,
+ self->parameter->width,
+ self->parameter->precision,
+ self->parameter->base);
+}
+
+/*************************************************************************
+ * trio_print_uint [public]
+ */
+void
+trio_print_uint
+TRIO_ARGS2((ref, number),
+ trio_pointer_t ref,
+ unsigned int number)
+{
+ trio_reference_t *self = (trio_reference_t *)ref;
+
+ TrioWriteNumber(self->data,
+ (trio_uintmax_t)number,
+ self->parameter->flags | FLAGS_UNSIGNED,
+ self->parameter->width,
+ self->parameter->precision,
+ self->parameter->base);
+}
+
+/*************************************************************************
+ * trio_print_double [public]
+ */
+void
+trio_print_double
+TRIO_ARGS2((ref, number),
+ trio_pointer_t ref,
+ double number)
+{
+ trio_reference_t *self = (trio_reference_t *)ref;
+
+ TrioWriteDouble(self->data,
+ number,
+ self->parameter->flags,
+ self->parameter->width,
+ self->parameter->precision,
+ self->parameter->base);
+}
+
+/*************************************************************************
+ * trio_print_string [public]
+ */
+void
+trio_print_string
+TRIO_ARGS2((ref, string),
+ trio_pointer_t ref,
+ char *string)
+{
+ trio_reference_t *self = (trio_reference_t *)ref;
+
+ TrioWriteString(self->data,
+ string,
+ self->parameter->flags,
+ self->parameter->width,
+ self->parameter->precision);
+}
+
+/*************************************************************************
+ * trio_print_ref [public]
+ */
+int
+trio_print_ref
+TRIO_VARGS3((ref, format, va_alist),
+ trio_pointer_t ref,
+ TRIO_CONST char *format,
+ TRIO_VA_DECL)
+{
+ int status;
+ va_list arglist;
+
+ assert(VALID(format));
+
+ TRIO_VA_START(arglist, format);
+ status = TrioFormatRef((trio_reference_t *)ref, format, &arglist, NULL);
+ TRIO_VA_END(arglist);
+ return status;
+}
+
+/*************************************************************************
+ * trio_vprint_ref [public]
+ */
+int
+trio_vprint_ref
+TRIO_ARGS3((ref, format, arglist),
+ trio_pointer_t ref,
+ TRIO_CONST char *format,
+ va_list arglist)
+{
+ assert(VALID(format));
+
+ return TrioFormatRef((trio_reference_t *)ref, format, &arglist, NULL);
+}
+
+/*************************************************************************
+ * trio_printv_ref [public]
+ */
+int
+trio_printv_ref
+TRIO_ARGS3((ref, format, argarray),
+ trio_pointer_t ref,
+ TRIO_CONST char *format,
+ trio_pointer_t *argarray)
+{
+ assert(VALID(format));
+
+ return TrioFormatRef((trio_reference_t *)ref, format, NULL, argarray);
+}
+
+#endif /* TRIO_EXTENSION */
+
+/*************************************************************************
+ * trio_print_pointer [public]
+ */
+void
+trio_print_pointer
+TRIO_ARGS2((ref, pointer),
+ trio_pointer_t ref,
+ trio_pointer_t pointer)
+{
+ trio_reference_t *self = (trio_reference_t *)ref;
+ trio_flags_t flags;
+ trio_uintmax_t number;
+
+ if (NULL == pointer)
+ {
+ TRIO_CONST char *string = internalNullString;
+ while (*string)
+ self->data->OutStream(self->data, *string++);
+ }
+ else
+ {
+ /*
+ * The subtraction of the null pointer is a workaround
+ * to avoid a compiler warning. The performance overhead
+ * is negligible (and likely to be removed by an
+ * optimizing compiler). The (char *) casting is done
+ * to please ANSI C++.
+ */
+ number = (trio_uintmax_t)((char *)pointer - (char *)0);
+ /* Shrink to size of pointer */
+ number &= (trio_uintmax_t)-1;
+ flags = self->parameter->flags;
+ flags |= (FLAGS_UNSIGNED | FLAGS_ALTERNATIVE |
+ FLAGS_NILPADDING);
+ TrioWriteNumber(self->data,
+ number,
+ flags,
+ POINTER_WIDTH,
+ NO_PRECISION,
+ BASE_HEX);
+ }
+}
+
+/** @} End of UserDefined documentation module */
+
+/*************************************************************************
+ *
+ * LOCALES
+ *
+ ************************************************************************/
+
+/*************************************************************************
+ * trio_locale_set_decimal_point
+ *
+ * Decimal point can only be one character. The input argument is a
+ * string to enable multibyte characters. At most MB_LEN_MAX characters
+ * will be used.
+ */
+TRIO_PUBLIC void
+trio_locale_set_decimal_point
+TRIO_ARGS1((decimalPoint),
+ char *decimalPoint)
+{
+#if defined(USE_LOCALE)
+ if (NULL == internalLocaleValues)
+ {
+ TrioSetLocale();
+ }
+#endif
+ internalDecimalPointLength = trio_length(decimalPoint);
+ if (internalDecimalPointLength == 1)
+ {
+ internalDecimalPoint = *decimalPoint;
+ }
+ else
+ {
+ internalDecimalPoint = NIL;
+ trio_copy_max(internalDecimalPointString,
+ sizeof(internalDecimalPointString),
+ decimalPoint);
+ }
+}
+
+/*************************************************************************
+ * trio_locale_set_thousand_separator
+ *
+ * See trio_locale_set_decimal_point
+ */
+TRIO_PUBLIC void
+trio_locale_set_thousand_separator
+TRIO_ARGS1((thousandSeparator),
+ char *thousandSeparator)
+{
+#if defined(USE_LOCALE)
+ if (NULL == internalLocaleValues)
+ {
+ TrioSetLocale();
+ }
+#endif
+ trio_copy_max(internalThousandSeparator,
+ sizeof(internalThousandSeparator),
+ thousandSeparator);
+ internalThousandSeparatorLength = trio_length(internalThousandSeparator);
+}
+
+/*************************************************************************
+ * trio_locale_set_grouping
+ *
+ * Array of bytes. Reversed order.
+ *
+ * CHAR_MAX : No further grouping
+ * 0 : Repeat last group for the remaining digits (not necessary
+ * as C strings are zero-terminated)
+ * n : Set current group to n
+ *
+ * Same order as the grouping attribute in LC_NUMERIC.
+ */
+TRIO_PUBLIC void
+trio_locale_set_grouping
+TRIO_ARGS1((grouping),
+ char *grouping)
+{
+#if defined(USE_LOCALE)
+ if (NULL == internalLocaleValues)
+ {
+ TrioSetLocale();
+ }
+#endif
+ trio_copy_max(internalGrouping,
+ sizeof(internalGrouping),
+ grouping);
+}
+
+
+/*************************************************************************
+ *
+ * SCANNING
+ *
+ ************************************************************************/
+
+/*************************************************************************
+ * TrioSkipWhitespaces
+ */
+TRIO_PRIVATE int
+TrioSkipWhitespaces
+TRIO_ARGS1((self),
+ trio_class_t *self)
+{
+ int ch;
+
+ ch = self->current;
+ while (isspace(ch))
+ {
+ self->InStream(self, &ch);
+ }
+ return ch;
+}
+
+/*************************************************************************
+ * TrioGetCollation
+ */
+#if TRIO_EXTENSION
+TRIO_PRIVATE void
+TrioGetCollation(TRIO_NOARGS)
+{
+ int i;
+ int j;
+ int k;
+ char first[2];
+ char second[2];
+
+ /* This is computationally expensive */
+ first[1] = NIL;
+ second[1] = NIL;
+ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+ {
+ k = 0;
+ first[0] = (char)i;
+ for (j = 0; j < MAX_CHARACTER_CLASS; j++)
+ {
+ second[0] = (char)j;
+ if (trio_equal_locale(first, second))
+ internalCollationArray[i][k++] = (char)j;
+ }
+ internalCollationArray[i][k] = NIL;
+ }
+}
+#endif
+
+/*************************************************************************
+ * TrioGetCharacterClass
+ *
+ * FIXME:
+ * multibyte
+ */
+TRIO_PRIVATE int
+TrioGetCharacterClass
+TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass),
+ TRIO_CONST char *format,
+ int *indexPointer,
+ trio_flags_t *flagsPointer,
+ int *characterclass)
+{
+ int index = *indexPointer;
+ int i;
+ char ch;
+ char range_begin;
+ char range_end;
+
+ *flagsPointer &= ~FLAGS_EXCLUDE;
+
+ if (format[index] == QUALIFIER_CIRCUMFLEX)
+ {
+ *flagsPointer |= FLAGS_EXCLUDE;
+ index++;
+ }
+ /*
+ * If the ungroup character is at the beginning of the scanlist,
+ * it will be part of the class, and a second ungroup character
+ * must follow to end the group.
+ */
+ if (format[index] == SPECIFIER_UNGROUP)
+ {
+ characterclass[(int)SPECIFIER_UNGROUP]++;
+ index++;
+ }
+ /*
+ * Minus is used to specify ranges. To include minus in the class,
+ * it must be at the beginning of the list
+ */
+ if (format[index] == QUALIFIER_MINUS)
+ {
+ characterclass[(int)QUALIFIER_MINUS]++;
+ index++;
+ }
+ /* Collect characters */
+ for (ch = format[index];
+ (ch != SPECIFIER_UNGROUP) && (ch != NIL);
+ ch = format[++index])
+ {
+ switch (ch)
+ {
+ case QUALIFIER_MINUS: /* Scanlist ranges */
+
+ /*
+ * Both C99 and UNIX98 describes ranges as implementation-
+ * defined.
+ *
+ * We support the following behaviour (although this may
+ * change as we become wiser)
+ * - only increasing ranges, ie. [a-b] but not [b-a]
+ * - transitive ranges, ie. [a-b-c] == [a-c]
+ * - trailing minus, ie. [a-] is interpreted as an 'a'
+ * and a '-'
+ * - duplicates (although we can easily convert these
+ * into errors)
+ */
+ range_begin = format[index - 1];
+ range_end = format[++index];
+ if (range_end == SPECIFIER_UNGROUP)
+ {
+ /* Trailing minus is included */
+ characterclass[(int)ch]++;
+ ch = range_end;
+ break; /* for */
+ }
+ if (range_end == NIL)
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
+ if (range_begin > range_end)
+ return TRIO_ERROR_RETURN(TRIO_ERANGE, index);
+
+ for (i = (int)range_begin; i <= (int)range_end; i++)
+ characterclass[i]++;
+
+ ch = range_end;
+ break;
+
+#if TRIO_EXTENSION
+
+ case SPECIFIER_GROUP:
+
+ switch (format[index + 1])
+ {
+ case QUALIFIER_DOT: /* Collating symbol */
+ /*
+ * FIXME: This will be easier to implement when multibyte
+ * characters have been implemented. Until now, we ignore
+ * this feature.
+ */
+ for (i = index + 2; ; i++)
+ {
+ if (format[i] == NIL)
+ /* Error in syntax */
+ return -1;
+ else if (format[i] == QUALIFIER_DOT)
+ break; /* for */
+ }
+ if (format[++i] != SPECIFIER_UNGROUP)
+ return -1;
+
+ index = i;
+ break;
+
+ case QUALIFIER_EQUAL: /* Equivalence class expressions */
+ {
+ unsigned int j;
+ unsigned int k;
+
+ if (internalCollationUnconverted)
+ {
+ /* Lazy evaluation of collation array */
+ TrioGetCollation();
+ internalCollationUnconverted = FALSE;
+ }
+ for (i = index + 2; ; i++)
+ {
+ if (format[i] == NIL)
+ /* Error in syntax */
+ return -1;
+ else if (format[i] == QUALIFIER_EQUAL)
+ break; /* for */
+ else
+ {
+ /* Mark any equivalent character */
+ k = (unsigned int)format[i];
+ for (j = 0; internalCollationArray[k][j] != NIL; j++)
+ characterclass[(int)internalCollationArray[k][j]]++;
+ }
+ }
+ if (format[++i] != SPECIFIER_UNGROUP)
+ return -1;
+
+ index = i;
+ }
+ break;
+
+ case QUALIFIER_COLON: /* Character class expressions */
+
+ if (trio_equal_max(CLASS_ALNUM, sizeof(CLASS_ALNUM) - 1,
+ &format[index]))
+ {
+ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+ if (isalnum(i))
+ characterclass[i]++;
+ index += sizeof(CLASS_ALNUM) - 1;
+ }
+ else if (trio_equal_max(CLASS_ALPHA, sizeof(CLASS_ALPHA) - 1,
+ &format[index]))
+ {
+ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+ if (isalpha(i))
+ characterclass[i]++;
+ index += sizeof(CLASS_ALPHA) - 1;
+ }
+ else if (trio_equal_max(CLASS_CNTRL, sizeof(CLASS_CNTRL) - 1,
+ &format[index]))
+ {
+ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+ if (iscntrl(i))
+ characterclass[i]++;
+ index += sizeof(CLASS_CNTRL) - 1;
+ }
+ else if (trio_equal_max(CLASS_DIGIT, sizeof(CLASS_DIGIT) - 1,
+ &format[index]))
+ {
+ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+ if (isdigit(i))
+ characterclass[i]++;
+ index += sizeof(CLASS_DIGIT) - 1;
+ }
+ else if (trio_equal_max(CLASS_GRAPH, sizeof(CLASS_GRAPH) - 1,
+ &format[index]))
+ {
+ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+ if (isgraph(i))
+ characterclass[i]++;
+ index += sizeof(CLASS_GRAPH) - 1;
+ }
+ else if (trio_equal_max(CLASS_LOWER, sizeof(CLASS_LOWER) - 1,
+ &format[index]))
+ {
+ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+ if (islower(i))
+ characterclass[i]++;
+ index += sizeof(CLASS_LOWER) - 1;
+ }
+ else if (trio_equal_max(CLASS_PRINT, sizeof(CLASS_PRINT) - 1,
+ &format[index]))
+ {
+ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+ if (isprint(i))
+ characterclass[i]++;
+ index += sizeof(CLASS_PRINT) - 1;
+ }
+ else if (trio_equal_max(CLASS_PUNCT, sizeof(CLASS_PUNCT) - 1,
+ &format[index]))
+ {
+ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+ if (ispunct(i))
+ characterclass[i]++;
+ index += sizeof(CLASS_PUNCT) - 1;
+ }
+ else if (trio_equal_max(CLASS_SPACE, sizeof(CLASS_SPACE) - 1,
+ &format[index]))
+ {
+ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+ if (isspace(i))
+ characterclass[i]++;
+ index += sizeof(CLASS_SPACE) - 1;
+ }
+ else if (trio_equal_max(CLASS_UPPER, sizeof(CLASS_UPPER) - 1,
+ &format[index]))
+ {
+ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+ if (isupper(i))
+ characterclass[i]++;
+ index += sizeof(CLASS_UPPER) - 1;
+ }
+ else if (trio_equal_max(CLASS_XDIGIT, sizeof(CLASS_XDIGIT) - 1,
+ &format[index]))
+ {
+ for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+ if (isxdigit(i))
+ characterclass[i]++;
+ index += sizeof(CLASS_XDIGIT) - 1;
+ }
+ else
+ {
+ characterclass[(int)ch]++;
+ }
+ break;
+
+ default:
+ characterclass[(int)ch]++;
+ break;
+ }
+ break;
+
+#endif /* TRIO_EXTENSION */
+
+ default:
+ characterclass[(int)ch]++;
+ break;
+ }
+ }
+ return 0;
+}
+
+/*************************************************************************
+ * TrioReadNumber
+ *
+ * We implement our own number conversion in preference of strtol and
+ * strtoul, because we must handle 'long long' and thousand separators.
+ */
+TRIO_PRIVATE BOOLEAN_T
+TrioReadNumber
+TRIO_ARGS5((self, target, flags, width, base),
+ trio_class_t *self,
+ trio_uintmax_t *target,
+ trio_flags_t flags,
+ int width,
+ int base)
+{
+ trio_uintmax_t number = 0;
+ int digit;
+ int count;
+ BOOLEAN_T isNegative = FALSE;
+ BOOLEAN_T gotNumber = FALSE;
+ int j;
+
+ assert(VALID(self));
+ assert(VALID(self->InStream));
+ assert((base >= MIN_BASE && base <= MAX_BASE) || (base == NO_BASE));
+
+ if (internalDigitsUnconverted)
+ {
+ /* Lazy evaluation of digits array */
+ memset(internalDigitArray, -1, sizeof(internalDigitArray));
+ for (j = 0; j < (int)sizeof(internalDigitsLower) - 1; j++)
+ {
+ internalDigitArray[(int)internalDigitsLower[j]] = j;
+ internalDigitArray[(int)internalDigitsUpper[j]] = j;
+ }
+ internalDigitsUnconverted = FALSE;
+ }
+
+ TrioSkipWhitespaces(self);
+
+ if (!(flags & FLAGS_UNSIGNED))
+ {
+ /* Leading sign */
+ if (self->current == '+')
+ {
+ self->InStream(self, NULL);
+ }
+ else if (self->current == '-')
+ {
+ self->InStream(self, NULL);
+ isNegative = TRUE;
+ }
+ }
+
+ count = self->processed;
+
+ if (flags & FLAGS_ALTERNATIVE)
+ {
+ switch (base)
+ {
+ case NO_BASE:
+ case BASE_OCTAL:
+ case BASE_HEX:
+ case BASE_BINARY:
+ if (self->current == '0')
+ {
+ self->InStream(self, NULL);
+ if (self->current)
+ {
+ if ((base == BASE_HEX) &&
+ (trio_to_upper(self->current) == 'X'))
+ {
+ self->InStream(self, NULL);
+ }
+ else if ((base == BASE_BINARY) &&
+ (trio_to_upper(self->current) == 'B'))
+ {
+ self->InStream(self, NULL);
+ }
+ }
+ }
+ else
+ return FALSE;
+ break;
+ default:
+ break;
+ }
+ }
+
+ while (((width == NO_WIDTH) || (self->processed - count < width)) &&
+ (! ((self->current == EOF) || isspace(self->current))))
+ {
+ if (isascii(self->current))
+ {
+ digit = internalDigitArray[self->current];
+ /* Abort if digit is not allowed in the specified base */
+ if ((digit == -1) || (digit >= base))
+ break;
+ }
+ else if (flags & FLAGS_QUOTE)
+ {
+ /* Compare with thousands separator */
+ for (j = 0; internalThousandSeparator[j] && self->current; j++)
+ {
+ if (internalThousandSeparator[j] != self->current)
+ break;
+
+ self->InStream(self, NULL);
+ }
+ if (internalThousandSeparator[j])
+ break; /* Mismatch */
+ else
+ continue; /* Match */
+ }
+ else
+ break;
+
+ number *= base;
+ number += digit;
+ gotNumber = TRUE; /* we need at least one digit */
+
+ self->InStream(self, NULL);
+ }
+
+ /* Was anything read at all? */
+ if (!gotNumber)
+ return FALSE;
+
+ if (target)
+ *target = (isNegative) ? -((trio_intmax_t)number) : number;
+ return TRUE;
+}
+
+/*************************************************************************
+ * TrioReadChar
+ */
+TRIO_PRIVATE int
+TrioReadChar
+TRIO_ARGS4((self, target, flags, width),
+ trio_class_t *self,
+ char *target,
+ trio_flags_t flags,
+ int width)
+{
+ int i;
+ char ch;
+ trio_uintmax_t number;
+
+ assert(VALID(self));
+ assert(VALID(self->InStream));
+
+ for (i = 0;
+ (self->current != EOF) && (i < width);
+ i++)
+ {
+ ch = (char)self->current;
+ self->InStream(self, NULL);
+ if ((flags & FLAGS_ALTERNATIVE) && (ch == CHAR_BACKSLASH))
+ {
+ switch (self->current)
+ {
+ case '\\': ch = '\\'; break;
+ case 'a': ch = '\007'; break;
+ case 'b': ch = '\b'; break;
+ case 'f': ch = '\f'; break;
+ case 'n': ch = '\n'; break;
+ case 'r': ch = '\r'; break;
+ case 't': ch = '\t'; break;
+ case 'v': ch = '\v'; break;
+ default:
+ if (isdigit(self->current))
+ {
+ /* Read octal number */
+ if (!TrioReadNumber(self, &number, 0, 3, BASE_OCTAL))
+ return 0;
+ ch = (char)number;
+ }
+ else if (trio_to_upper(self->current) == 'X')
+ {
+ /* Read hexadecimal number */
+ self->InStream(self, NULL);
+ if (!TrioReadNumber(self, &number, 0, 2, BASE_HEX))
+ return 0;
+ ch = (char)number;
+ }
+ else
+ {
+ ch = (char)self->current;
+ }
+ break;
+ }
+ }
+
+ if (target)
+ target[i] = ch;
+ }
+ return i + 1;
+}
+
+/*************************************************************************
+ * TrioReadString
+ */
+TRIO_PRIVATE BOOLEAN_T
+TrioReadString
+TRIO_ARGS4((self, target, flags, width),
+ trio_class_t *self,
+ char *target,
+ trio_flags_t flags,
+ int width)
+{
+ int i;
+
+ assert(VALID(self));
+ assert(VALID(self->InStream));
+
+ TrioSkipWhitespaces(self);
+
+ /*
+ * Continue until end of string is reached, a whitespace is encountered,
+ * or width is exceeded
+ */
+ for (i = 0;
+ ((width == NO_WIDTH) || (i < width)) &&
+ (! ((self->current == EOF) || isspace(self->current)));
+ i++)
+ {
+ if (TrioReadChar(self, (target ? &target[i] : 0), flags, 1) == 0)
+ break; /* for */
+ }
+ if (target)
+ target[i] = NIL;
+ return TRUE;
+}
+
+/*************************************************************************
+ * TrioReadWideChar
+ */
+#if TRIO_WIDECHAR
+TRIO_PRIVATE int
+TrioReadWideChar
+TRIO_ARGS4((self, target, flags, width),
+ trio_class_t *self,
+ trio_wchar_t *target,
+ trio_flags_t flags,
+ int width)
+{
+ int i;
+ int j;
+ int size;
+ int amount = 0;
+ trio_wchar_t wch;
+ char buffer[MB_LEN_MAX + 1];
+
+ assert(VALID(self));
+ assert(VALID(self->InStream));
+
+ for (i = 0;
+ (self->current != EOF) && (i < width);
+ i++)
+ {
+ if (isascii(self->current))
+ {
+ if (TrioReadChar(self, buffer, flags, 1) == 0)
+ return 0;
+ buffer[1] = NIL;
+ }
+ else
+ {
+ /*
+ * Collect a multibyte character, by enlarging buffer until
+ * it contains a fully legal multibyte character, or the
+ * buffer is full.
+ */
+ j = 0;
+ do
+ {
+ buffer[j++] = (char)self->current;
+ buffer[j] = NIL;
+ self->InStream(self, NULL);
+ }
+ while ((j < (int)sizeof(buffer)) && (mblen(buffer, (size_t)j) != j));
+ }
+ if (target)
+ {
+ size = mbtowc(&wch, buffer, sizeof(buffer));
+ if (size > 0)
+ target[i] = wch;
+ }
+ amount += size;
+ self->InStream(self, NULL);
+ }
+ return amount;
+}
+#endif /* TRIO_WIDECHAR */
+
+/*************************************************************************
+ * TrioReadWideString
+ */
+#if TRIO_WIDECHAR
+TRIO_PRIVATE BOOLEAN_T
+TrioReadWideString
+TRIO_ARGS4((self, target, flags, width),
+ trio_class_t *self,
+ trio_wchar_t *target,
+ trio_flags_t flags,
+ int width)
+{
+ int i;
+ int size;
+
+ assert(VALID(self));
+ assert(VALID(self->InStream));
+
+ TrioSkipWhitespaces(self);
+
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
+ (void)mblen(NULL, 0);
+#endif
+
+ /*
+ * Continue until end of string is reached, a whitespace is encountered,
+ * or width is exceeded
+ */
+ for (i = 0;
+ ((width == NO_WIDTH) || (i < width)) &&
+ (! ((self->current == EOF) || isspace(self->current)));
+ )
+ {
+ size = TrioReadWideChar(self, &target[i], flags, 1);
+ if (size == 0)
+ break; /* for */
+
+ i += size;
+ }
+ if (target)
+ target[i] = WCONST('\0');
+ return TRUE;
+}
+#endif /* TRIO_WIDECHAR */
+
+/*************************************************************************
+ * TrioReadGroup
+ *
+ * FIXME: characterclass does not work with multibyte characters
+ */
+TRIO_PRIVATE BOOLEAN_T
+TrioReadGroup
+TRIO_ARGS5((self, target, characterclass, flags, width),
+ trio_class_t *self,
+ char *target,
+ int *characterclass,
+ trio_flags_t flags,
+ int width)
+{
+ int ch;
+ int i;
+
+ assert(VALID(self));
+ assert(VALID(self->InStream));
+
+ ch = self->current;
+ for (i = 0;
+ ((width == NO_WIDTH) || (i < width)) &&
+ (! ((ch == EOF) ||
+ (((flags & FLAGS_EXCLUDE) != 0) ^ (characterclass[ch] == 0))));
+ i++)
+ {
+ if (target)
+ target[i] = (char)ch;
+ self->InStream(self, &ch);
+ }
+
+ if (target)
+ target[i] = NIL;
+ return TRUE;
+}
+
+/*************************************************************************
+ * TrioReadDouble
+ *
+ * FIXME:
+ * add long double
+ * handle base
+ */
+TRIO_PRIVATE BOOLEAN_T
+TrioReadDouble
+TRIO_ARGS4((self, target, flags, width),
+ trio_class_t *self,
+ trio_pointer_t target,
+ trio_flags_t flags,
+ int width)
+{
+ int ch;
+ char doubleString[512];
+ int index = 0;
+ int start;
+ int j;
+ BOOLEAN_T isHex = FALSE;
+
+ doubleString[0] = 0;
+
+ if ((width == NO_WIDTH) || (width > (int)sizeof(doubleString) - 1))
+ width = sizeof(doubleString) - 1;
+
+ TrioSkipWhitespaces(self);
+
+ /*
+ * Read entire double number from stream. trio_to_double requires
+ * a string as input, but InStream can be anything, so we have to
+ * collect all characters.
+ */
+ ch = self->current;
+ if ((ch == '+') || (ch == '-'))
+ {
+ doubleString[index++] = (char)ch;
+ self->InStream(self, &ch);
+ width--;
+ }
+
+ start = index;
+ switch (ch)
+ {
+ case 'n':
+ case 'N':
+ /* Not-a-number */
+ if (index != 0)
+ break;
+ /* FALLTHROUGH */
+ case 'i':
+ case 'I':
+ /* Infinity */
+ while (isalpha(ch) && (index - start < width))
+ {
+ doubleString[index++] = (char)ch;
+ self->InStream(self, &ch);
+ }
+ doubleString[index] = NIL;
+
+ /* Case insensitive string comparison */
+ if (trio_equal(&doubleString[start], INFINITE_UPPER) ||
+ trio_equal(&doubleString[start], LONG_INFINITE_UPPER))
+ {
+ if (flags & FLAGS_LONGDOUBLE)
+ {
+ if ((start == 1) && (doubleString[0] == '-'))
+ {
+ *((trio_long_double_t *)target) = trio_ninf();
+ }
+ else
+ {
+ *((trio_long_double_t *)target) = trio_pinf();
+ }
+ }
+ else
+ {
+ if ((start == 1) && (doubleString[0] == '-'))
+ {
+ *((double *)target) = trio_ninf();
+ }
+ else
+ {
+ *((double *)target) = trio_pinf();
+ }
+ }
+ return TRUE;
+ }
+ if (trio_equal(doubleString, NAN_UPPER))
+ {
+ /* NaN must not have a preceeding + nor - */
+ if (flags & FLAGS_LONGDOUBLE)
+ {
+ *((trio_long_double_t *)target) = trio_nan();
+ }
+ else
+ {
+ *((double *)target) = trio_nan();
+ }
+ return TRUE;
+ }
+ return FALSE;
+
+ case '0':
+ doubleString[index++] = (char)ch;
+ self->InStream(self, &ch);
+ if (trio_to_upper(ch) == 'X')
+ {
+ isHex = TRUE;
+ doubleString[index++] = (char)ch;
+ self->InStream(self, &ch);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ while ((ch != EOF) && (index - start < width))
+ {
+ /* Integer part */
+ if (isHex ? isxdigit(ch) : isdigit(ch))
+ {
+ doubleString[index++] = (char)ch;
+ self->InStream(self, &ch);
+ }
+ else if (flags & FLAGS_QUOTE)
+ {
+ /* Compare with thousands separator */
+ for (j = 0; internalThousandSeparator[j] && self->current; j++)
+ {
+ if (internalThousandSeparator[j] != self->current)
+ break;
+
+ self->InStream(self, &ch);
+ }
+ if (internalThousandSeparator[j])
+ break; /* Mismatch */
+ else
+ continue; /* Match */
+ }
+ else
+ break; /* while */
+ }
+ if (ch == '.')
+ {
+ /* Decimal part */
+ doubleString[index++] = (char)ch;
+ self->InStream(self, &ch);
+ while ((isHex ? isxdigit(ch) : isdigit(ch)) &&
+ (index - start < width))
+ {
+ doubleString[index++] = (char)ch;
+ self->InStream(self, &ch);
+ }
+ if (isHex ? (trio_to_upper(ch) == 'P') : (trio_to_upper(ch) == 'E'))
+ {
+ /* Exponent */
+ doubleString[index++] = (char)ch;
+ self->InStream(self, &ch);
+ if ((ch == '+') || (ch == '-'))
+ {
+ doubleString[index++] = (char)ch;
+ self->InStream(self, &ch);
+ }
+ while (isdigit(ch) && (index - start < width))
+ {
+ doubleString[index++] = (char)ch;
+ self->InStream(self, &ch);
+ }
+ }
+ }
+
+ if ((index == start) || (*doubleString == NIL))
+ return FALSE;
+
+ doubleString[index] = 0;
+
+ if (flags & FLAGS_LONGDOUBLE)
+ {
+ *((trio_long_double_t *)target) = trio_to_long_double(doubleString, NULL);
+ }
+ else
+ {
+ *((double *)target) = trio_to_double(doubleString, NULL);
+ }
+ return TRUE;
+}
+
+/*************************************************************************
+ * TrioReadPointer
+ */
+TRIO_PRIVATE BOOLEAN_T
+TrioReadPointer
+TRIO_ARGS3((self, target, flags),
+ trio_class_t *self,
+ trio_pointer_t *target,
+ trio_flags_t flags)
+{
+ trio_uintmax_t number;
+ char buffer[sizeof(internalNullString)];
+
+ flags |= (FLAGS_UNSIGNED | FLAGS_ALTERNATIVE | FLAGS_NILPADDING);
+
+ if (TrioReadNumber(self,
+ &number,
+ flags,
+ POINTER_WIDTH,
+ BASE_HEX))
+ {
+ /*
+ * The strange assignment of number is a workaround for a compiler
+ * warning
+ */
+ if (target)
+ *target = (char *)0 + number;
+ return TRUE;
+ }
+ else if (TrioReadString(self,
+ (flags & FLAGS_IGNORE)
+ ? NULL
+ : buffer,
+ 0,
+ sizeof(internalNullString) - 1))
+ {
+ if (trio_equal_case(buffer, internalNullString))
+ {
+ if (target)
+ *target = NULL;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/*************************************************************************
+ * TrioScanProcess
+ */
+TRIO_PRIVATE int
+TrioScanProcess
+TRIO_ARGS3((data, format, parameters),
+ trio_class_t *data,
+ TRIO_CONST char *format,
+ trio_parameter_t *parameters)
+{
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
+ int charlen;
+ int cnt;
+#endif
+ int assignment;
+ int ch;
+ int index; /* Index of format string */
+ int i; /* Index of current parameter */
+ trio_flags_t flags;
+ int width;
+ int base;
+ trio_pointer_t pointer;
+
+ assignment = 0;
+ i = 0;
+ index = 0;
+ data->InStream(data, &ch);
+
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
+ (void)mblen(NULL, 0);
+#endif
+
+ while (format[index])
+ {
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
+ if (! isascii(format[index]))
+ {
+ charlen = mblen(&format[index], MB_LEN_MAX);
+ if (charlen != -1)
+ {
+ /* Compare multibyte characters in format string */
+ for (cnt = 0; cnt < charlen - 1; cnt++)
+ {
+ if (ch != format[index + cnt])
+ {
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
+ }
+ data->InStream(data, &ch);
+ }
+ continue; /* while characters left in formatting string */
+ }
+ }
+#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
+
+ if ((EOF == ch) && (parameters[i].type != FORMAT_COUNT))
+ {
+ return (assignment > 0) ? assignment : EOF;
+ }
+
+ if (CHAR_IDENTIFIER == format[index])
+ {
+ if (CHAR_IDENTIFIER == format[index + 1])
+ {
+ /* Two % in format matches one % in input stream */
+ if (CHAR_IDENTIFIER == ch)
+ {
+ data->InStream(data, &ch);
+ index += 2;
+ continue; /* while format chars left */
+ }
+ else
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
+ }
+
+ /* Skip the parameter entries */
+ while (parameters[i].type == FORMAT_PARAMETER)
+ i++;
+
+ flags = parameters[i].flags;
+ /* Find width */
+ width = parameters[i].width;
+ if (flags & FLAGS_WIDTH_PARAMETER)
+ {
+ /* Get width from parameter list */
+ width = (int)parameters[width].data.number.as_signed;
+ }
+ /* Find base */
+ base = parameters[i].base;
+ if (flags & FLAGS_BASE_PARAMETER)
+ {
+ /* Get base from parameter list */
+ base = (int)parameters[base].data.number.as_signed;
+ }
+
+ switch (parameters[i].type)
+ {
+ case FORMAT_INT:
+ {
+ trio_uintmax_t number;
+
+ if (0 == base)
+ base = BASE_DECIMAL;
+
+ if (!TrioReadNumber(data,
+ &number,
+ flags,
+ width,
+ base))
+ return assignment;
+
+ if (!(flags & FLAGS_IGNORE))
+ {
+ assignment++;
+
+ pointer = parameters[i].data.pointer;
+#if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
+ if (flags & FLAGS_SIZE_T)
+ *(size_t *)pointer = (size_t)number;
+ else
+#endif
+#if defined(QUALIFIER_PTRDIFF_T)
+ if (flags & FLAGS_PTRDIFF_T)
+ *(ptrdiff_t *)pointer = (ptrdiff_t)number;
+ else
+#endif
+#if defined(QUALIFIER_INTMAX_T)
+ if (flags & FLAGS_INTMAX_T)
+ *(trio_intmax_t *)pointer = (trio_intmax_t)number;
+ else
+#endif
+ if (flags & FLAGS_QUAD)
+ *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)number;
+ else if (flags & FLAGS_LONG)
+ *(long int *)pointer = (long int)number;
+ else if (flags & FLAGS_SHORT)
+ *(short int *)pointer = (short int)number;
+ else
+ *(int *)pointer = (int)number;
+ }
+ }
+ break; /* FORMAT_INT */
+
+ case FORMAT_STRING:
+#if TRIO_WIDECHAR
+ if (flags & FLAGS_WIDECHAR)
+ {
+ if (!TrioReadWideString(data,
+ (flags & FLAGS_IGNORE)
+ ? NULL
+ : parameters[i].data.wstring,
+ flags,
+ width))
+ return assignment;
+ }
+ else
+#endif
+ {
+ if (!TrioReadString(data,
+ (flags & FLAGS_IGNORE)
+ ? NULL
+ : parameters[i].data.string,
+ flags,
+ width))
+ return assignment;
+ }
+ if (!(flags & FLAGS_IGNORE))
+ assignment++;
+ break; /* FORMAT_STRING */
+
+ case FORMAT_DOUBLE:
+ {
+ trio_pointer_t pointer;
+
+ if (flags & FLAGS_IGNORE)
+ {
+ pointer = NULL;
+ }
+ else
+ {
+ pointer = (flags & FLAGS_LONGDOUBLE)
+ ? (trio_pointer_t)parameters[i].data.longdoublePointer
+ : (trio_pointer_t)parameters[i].data.doublePointer;
+ }
+ if (!TrioReadDouble(data, pointer, flags, width))
+ {
+ return assignment;
+ }
+ if (!(flags & FLAGS_IGNORE))
+ {
+ assignment++;
+ }
+ break; /* FORMAT_DOUBLE */
+ }
+ case FORMAT_GROUP:
+ {
+ int characterclass[MAX_CHARACTER_CLASS + 1];
+ int rc;
+
+ /* Skip over modifiers */
+ while (format[index] != SPECIFIER_GROUP)
+ {
+ index++;
+ }
+ /* Skip over group specifier */
+ index++;
+
+ memset(characterclass, 0, sizeof(characterclass));
+ rc = TrioGetCharacterClass(format,
+ &index,
+ &flags,
+ characterclass);
+ if (rc < 0)
+ return rc;
+
+ if (!TrioReadGroup(data,
+ (flags & FLAGS_IGNORE)
+ ? NULL
+ : parameters[i].data.string,
+ characterclass,
+ flags,
+ parameters[i].width))
+ return assignment;
+ if (!(flags & FLAGS_IGNORE))
+ assignment++;
+ }
+ break; /* FORMAT_GROUP */
+
+ case FORMAT_COUNT:
+ pointer = parameters[i].data.pointer;
+ if (NULL != pointer)
+ {
+ int count = data->committed;
+ if (ch != EOF)
+ count--; /* a character is read, but is not consumed yet */
+#if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
+ if (flags & FLAGS_SIZE_T)
+ *(size_t *)pointer = (size_t)count;
+ else
+#endif
+#if defined(QUALIFIER_PTRDIFF_T)
+ if (flags & FLAGS_PTRDIFF_T)
+ *(ptrdiff_t *)pointer = (ptrdiff_t)count;
+ else
+#endif
+#if defined(QUALIFIER_INTMAX_T)
+ if (flags & FLAGS_INTMAX_T)
+ *(trio_intmax_t *)pointer = (trio_intmax_t)count;
+ else
+#endif
+ if (flags & FLAGS_QUAD)
+ {
+ *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)count;
+ }
+ else if (flags & FLAGS_LONG)
+ {
+ *(long int *)pointer = (long int)count;
+ }
+ else if (flags & FLAGS_SHORT)
+ {
+ *(short int *)pointer = (short int)count;
+ }
+ else
+ {
+ *(int *)pointer = (int)count;
+ }
+ }
+ break; /* FORMAT_COUNT */
+
+ case FORMAT_CHAR:
+#if TRIO_WIDECHAR
+ if (flags & FLAGS_WIDECHAR)
+ {
+ if (TrioReadWideChar(data,
+ (flags & FLAGS_IGNORE)
+ ? NULL
+ : parameters[i].data.wstring,
+ flags,
+ (width == NO_WIDTH) ? 1 : width) == 0)
+ return assignment;
+ }
+ else
+#endif
+ {
+ if (TrioReadChar(data,
+ (flags & FLAGS_IGNORE)
+ ? NULL
+ : parameters[i].data.string,
+ flags,
+ (width == NO_WIDTH) ? 1 : width) == 0)
+ return assignment;
+ }
+ if (!(flags & FLAGS_IGNORE))
+ assignment++;
+ break; /* FORMAT_CHAR */
+
+ case FORMAT_POINTER:
+ if (!TrioReadPointer(data,
+ (flags & FLAGS_IGNORE)
+ ? NULL
+ : (trio_pointer_t *)parameters[i].data.pointer,
+ flags))
+ return assignment;
+ if (!(flags & FLAGS_IGNORE))
+ assignment++;
+ break; /* FORMAT_POINTER */
+
+ case FORMAT_PARAMETER:
+ break; /* FORMAT_PARAMETER */
+
+ default:
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
+ }
+ ch = data->current;
+ index = parameters[i].indexAfterSpecifier;
+ i++;
+ }
+ else /* Not an % identifier */
+ {
+ if (isspace((int)format[index]))
+ {
+ /* Whitespaces may match any amount of whitespaces */
+ ch = TrioSkipWhitespaces(data);
+ }
+ else if (ch == format[index])
+ {
+ data->InStream(data, &ch);
+ }
+ else
+ return assignment;
+
+ index++;
+ }
+ }
+ return assignment;
+}
+
+/*************************************************************************
+ * TrioScan
+ */
+TRIO_PRIVATE int
+TrioScan
+TRIO_ARGS6((source, sourceSize, InStream, format, arglist, argarray),
+ trio_pointer_t source,
+ size_t sourceSize,
+ void (*InStream) TRIO_PROTO((trio_class_t *, int *)),
+ TRIO_CONST char *format,
+ va_list *arglist,
+ trio_pointer_t *argarray)
+{
+ int status;
+ trio_parameter_t parameters[MAX_PARAMETERS];
+ trio_class_t data;
+
+ assert(VALID(InStream));
+ assert(VALID(format));
+
+ memset(&data, 0, sizeof(data));
+ data.InStream = InStream;
+ data.location = (trio_pointer_t)source;
+ data.max = sourceSize;
+ data.error = 0;
+
+#if defined(USE_LOCALE)
+ if (NULL == internalLocaleValues)
+ {
+ TrioSetLocale();
+ }
+#endif
+
+ status = TrioParse(TYPE_SCAN, format, parameters, arglist, argarray);
+ if (status < 0)
+ return status;
+
+ status = TrioScanProcess(&data, format, parameters);
+ if (data.error != 0)
+ {
+ status = data.error;
+ }
+ return status;
+}
+
+/*************************************************************************
+ * TrioInStreamFile
+ */
+TRIO_PRIVATE void
+TrioInStreamFile
+TRIO_ARGS2((self, intPointer),
+ trio_class_t *self,
+ int *intPointer)
+{
+ FILE *file = (FILE *)self->location;
+
+ assert(VALID(self));
+ assert(VALID(file));
+
+ self->current = fgetc(file);
+ if (self->current == EOF)
+ {
+ self->error = (ferror(file))
+ ? TRIO_ERROR_RETURN(TRIO_ERRNO, 0)
+ : TRIO_ERROR_RETURN(TRIO_EOF, 0);
+ }
+ else
+ {
+ self->processed++;
+ self->committed++;
+ }
+
+ if (VALID(intPointer))
+ {
+ *intPointer = self->current;
+ }
+}
+
+/*************************************************************************
+ * TrioInStreamFileDescriptor
+ */
+TRIO_PRIVATE void
+TrioInStreamFileDescriptor
+TRIO_ARGS2((self, intPointer),
+ trio_class_t *self,
+ int *intPointer)
+{
+ int fd = *((int *)self->location);
+ int size;
+ unsigned char input;
+
+ assert(VALID(self));
+
+ size = read(fd, &input, sizeof(char));
+ if (size == -1)
+ {
+ self->error = TRIO_ERROR_RETURN(TRIO_ERRNO, 0);
+ self->current = EOF;
+ }
+ else
+ {
+ self->current = (size == 0) ? EOF : input;
+ }
+ if (self->current != EOF)
+ {
+ self->committed++;
+ self->processed++;
+ }
+
+ if (VALID(intPointer))
+ {
+ *intPointer = self->current;
+ }
+}
+
+/*************************************************************************
+ * TrioInStreamCustom
+ */
+TRIO_PRIVATE void
+TrioInStreamCustom
+TRIO_ARGS2((self, intPointer),
+ trio_class_t *self,
+ int *intPointer)
+{
+ trio_custom_t *data;
+
+ assert(VALID(self));
+ assert(VALID(self->location));
+
+ data = (trio_custom_t *)self->location;
+
+ self->current = (data->stream.in == NULL)
+ ? NIL
+ : (data->stream.in)(data->closure);
+
+ if (self->current == NIL)
+ {
+ self->current = EOF;
+ }
+ else
+ {
+ self->processed++;
+ self->committed++;
+ }
+
+ if (VALID(intPointer))
+ {
+ *intPointer = self->current;
+ }
+}
+
+/*************************************************************************
+ * TrioInStreamString
+ */
+TRIO_PRIVATE void
+TrioInStreamString
+TRIO_ARGS2((self, intPointer),
+ trio_class_t *self,
+ int *intPointer)
+{
+ unsigned char **buffer;
+
+ assert(VALID(self));
+ assert(VALID(self->location));
+
+ buffer = (unsigned char **)self->location;
+ self->current = (*buffer)[0];
+ if (self->current == NIL)
+ {
+ self->current = EOF;
+ }
+ else
+ {
+ (*buffer)++;
+ self->processed++;
+ self->committed++;
+ }
+
+ if (VALID(intPointer))
+ {
+ *intPointer = self->current;
+ }
+}
+
+/*************************************************************************
+ *
+ * Formatted scanning functions
+ *
+ ************************************************************************/
+
+#if defined(TRIO_DOCUMENTATION)
+# include "doc/doc_scanf.h"
+#endif
+/** @addtogroup Scanf
+ @{
+*/
+
+/*************************************************************************
+ * scanf
+ */
+
+/**
+ Scan characters from standard input stream.
+
+ @param format Formatting string.
+ @param ... Arguments.
+ @return Number of scanned characters.
+ */
+TRIO_PUBLIC int
+trio_scanf
+TRIO_VARGS2((format, va_alist),
+ TRIO_CONST char *format,
+ TRIO_VA_DECL)
+{
+ int status;
+ va_list args;
+
+ assert(VALID(format));
+
+ TRIO_VA_START(args, format);
+ status = TrioScan((trio_pointer_t)stdin, 0,
+ TrioInStreamFile,
+ format, &args, NULL);
+ TRIO_VA_END(args);
+ return status;
+}
+
+TRIO_PUBLIC int
+trio_vscanf
+TRIO_ARGS2((format, args),
+ TRIO_CONST char *format,
+ va_list args)
+{
+ assert(VALID(format));
+
+ return TrioScan((trio_pointer_t)stdin, 0,
+ TrioInStreamFile,
+ format, &args, NULL);
+}
+
+TRIO_PUBLIC int
+trio_scanfv
+TRIO_ARGS2((format, args),
+ TRIO_CONST char *format,
+ trio_pointer_t *args)
+{
+ assert(VALID(format));
+
+ return TrioScan((trio_pointer_t)stdin, 0,
+ TrioInStreamFile,
+ format, NULL, args);
+}
+
+/*************************************************************************
+ * fscanf
+ */
+TRIO_PUBLIC int
+trio_fscanf
+TRIO_VARGS3((file, format, va_alist),
+ FILE *file,
+ TRIO_CONST char *format,
+ TRIO_VA_DECL)
+{
+ int status;
+ va_list args;
+
+ assert(VALID(file));
+ assert(VALID(format));
+
+ TRIO_VA_START(args, format);
+ status = TrioScan((trio_pointer_t)file, 0,
+ TrioInStreamFile,
+ format, &args, NULL);
+ TRIO_VA_END(args);
+ return status;
+}
+
+TRIO_PUBLIC int
+trio_vfscanf
+TRIO_ARGS3((file, format, args),
+ FILE *file,
+ TRIO_CONST char *format,
+ va_list args)
+{
+ assert(VALID(file));
+ assert(VALID(format));
+
+ return TrioScan((trio_pointer_t)file, 0,
+ TrioInStreamFile,
+ format, &args, NULL);
+}
+
+TRIO_PUBLIC int
+trio_fscanfv
+TRIO_ARGS3((file, format, args),
+ FILE *file,
+ TRIO_CONST char *format,
+ trio_pointer_t *args)
+{
+ assert(VALID(file));
+ assert(VALID(format));
+
+ return TrioScan((trio_pointer_t)file, 0,
+ TrioInStreamFile,
+ format, NULL, args);
+}
+
+/*************************************************************************
+ * dscanf
+ */
+TRIO_PUBLIC int
+trio_dscanf
+TRIO_VARGS3((fd, format, va_alist),
+ int fd,
+ TRIO_CONST char *format,
+ TRIO_VA_DECL)
+{
+ int status;
+ va_list args;
+
+ assert(VALID(format));
+
+ TRIO_VA_START(args, format);
+ status = TrioScan((trio_pointer_t)&fd, 0,
+ TrioInStreamFileDescriptor,
+ format, &args, NULL);
+ TRIO_VA_END(args);
+ return status;
+}
+
+TRIO_PUBLIC int
+trio_vdscanf
+TRIO_ARGS3((fd, format, args),
+ int fd,
+ TRIO_CONST char *format,
+ va_list args)
+{
+ assert(VALID(format));
+
+ return TrioScan((trio_pointer_t)&fd, 0,
+ TrioInStreamFileDescriptor,
+ format, &args, NULL);
+}
+
+TRIO_PUBLIC int
+trio_dscanfv
+TRIO_ARGS3((fd, format, args),
+ int fd,
+ TRIO_CONST char *format,
+ trio_pointer_t *args)
+{
+ assert(VALID(format));
+
+ return TrioScan((trio_pointer_t)&fd, 0,
+ TrioInStreamFileDescriptor,
+ format, NULL, args);
+}
+
+/*************************************************************************
+ * cscanf
+ */
+TRIO_PUBLIC int
+trio_cscanf
+TRIO_VARGS4((stream, closure, format, va_alist),
+ trio_instream_t stream,
+ trio_pointer_t closure,
+ TRIO_CONST char *format,
+ TRIO_VA_DECL)
+{
+ int status;
+ va_list args;
+ trio_custom_t data;
+
+ assert(VALID(stream));
+ assert(VALID(format));
+
+ TRIO_VA_START(args, format);
+ data.stream.in = stream;
+ data.closure = closure;
+ status = TrioScan(&data, 0, TrioInStreamCustom, format, &args, NULL);
+ TRIO_VA_END(args);
+ return status;
+}
+
+TRIO_PUBLIC int
+trio_vcscanf
+TRIO_ARGS4((stream, closure, format, args),
+ trio_instream_t stream,
+ trio_pointer_t closure,
+ TRIO_CONST char *format,
+ va_list args)
+{
+ trio_custom_t data;
+
+ assert(VALID(stream));
+ assert(VALID(format));
+
+ data.stream.in = stream;
+ data.closure = closure;
+ return TrioScan(&data, 0, TrioInStreamCustom, format, &args, NULL);
+}
+
+TRIO_PUBLIC int
+trio_cscanfv
+TRIO_ARGS4((stream, closure, format, args),
+ trio_instream_t stream,
+ trio_pointer_t closure,
+ TRIO_CONST char *format,
+ trio_pointer_t *args)
+{
+ trio_custom_t data;
+
+ assert(VALID(stream));
+ assert(VALID(format));
+
+ data.stream.in = stream;
+ data.closure = closure;
+ return TrioScan(&data, 0, TrioInStreamCustom, format, NULL, args);
+}
+
+/*************************************************************************
+ * sscanf
+ */
+TRIO_PUBLIC int
+trio_sscanf
+TRIO_VARGS3((buffer, format, va_alist),
+ TRIO_CONST char *buffer,
+ TRIO_CONST char *format,
+ TRIO_VA_DECL)
+{
+ int status;
+ va_list args;
+
+ assert(VALID(buffer));
+ assert(VALID(format));
+
+ TRIO_VA_START(args, format);
+ status = TrioScan((trio_pointer_t)&buffer, 0,
+ TrioInStreamString,
+ format, &args, NULL);
+ TRIO_VA_END(args);
+ return status;
+}
+
+TRIO_PUBLIC int
+trio_vsscanf
+TRIO_ARGS3((buffer, format, args),
+ TRIO_CONST char *buffer,
+ TRIO_CONST char *format,
+ va_list args)
+{
+ assert(VALID(buffer));
+ assert(VALID(format));
+
+ return TrioScan((trio_pointer_t)&buffer, 0,
+ TrioInStreamString,
+ format, &args, NULL);
+}
+
+TRIO_PUBLIC int
+trio_sscanfv
+TRIO_ARGS3((buffer, format, args),
+ TRIO_CONST char *buffer,
+ TRIO_CONST char *format,
+ trio_pointer_t *args)
+{
+ assert(VALID(buffer));
+ assert(VALID(format));
+
+ return TrioScan((trio_pointer_t)&buffer, 0,
+ TrioInStreamString,
+ format, NULL, args);
+}
+
+/** @} End of Scanf documentation module */
+
+/*************************************************************************
+ * trio_strerror
+ */
+TRIO_PUBLIC TRIO_CONST char *
+trio_strerror
+TRIO_ARGS1((errorcode),
+ int errorcode)
+{
+ /* Textual versions of the error codes */
+ switch (TRIO_ERROR_CODE(errorcode))
+ {
+ case TRIO_EOF:
+ return "End of file";
+ case TRIO_EINVAL:
+ return "Invalid argument";
+ case TRIO_ETOOMANY:
+ return "Too many arguments";
+ case TRIO_EDBLREF:
+ return "Double reference";
+ case TRIO_EGAP:
+ return "Reference gap";
+ case TRIO_ENOMEM:
+ return "Out of memory";
+ case TRIO_ERANGE:
+ return "Invalid range";
+ case TRIO_ECUSTOM:
+ return "Custom error";
+ default:
+ return "Unknown";
+ }
+}
diff --git a/trio/trio.h b/trio/trio.h
new file mode 100644
index 00000000..82e65fcc
--- /dev/null
+++ b/trio/trio.h
@@ -0,0 +1,216 @@
+/*************************************************************************
+ *
+ * $Id: trio.h,v 1.16 2003/03/06 20:29:48 breese Exp $
+ *
+ * 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
+
+#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"
+
+#include <stdio.h>
+#include <stdlib.h>
+#if defined(TRIO_COMPILER_ANCIENT)
+# include <varargs.h>
+#else
+# include <stdarg.h>
+#endif
+
+#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 */
diff --git a/trio/triodef.h b/trio/triodef.h
new file mode 100644
index 00000000..400dfcfc
--- /dev/null
+++ b/trio/triodef.h
@@ -0,0 +1,220 @@
+/*************************************************************************
+ *
+ * $Id: triodef.h,v 1.18 2003/03/01 15:34:01 breese Exp $
+ *
+ * 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
+#elif defined(sun) || defined(__sun__)
+# if defined(__SVR4) || defined(__svr4__)
+# define TRIO_PLATFORM_SOLARIS
+# else
+# define TRIO_PLATFORM_SUNOS
+# endif
+#endif
+
+#if defined(__STDC__) || defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB)
+# 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
+
+/*
+ * Not all preprocessors supports the LL token.
+ */
+#if defined(TRIO_COMPILER_BCB)
+#else
+# define TRIO_COMPILER_SUPPORTS_LL
+#endif
+
+#endif /* TRIO_TRIODEF_H */
diff --git a/trio/trionan.c b/trio/trionan.c
new file mode 100644
index 00000000..4391477e
--- /dev/null
+++ b/trio/trionan.c
@@ -0,0 +1,901 @@
+/*************************************************************************
+ *
+ * $Id: trionan.c,v 1.26 2002/12/08 12:08:21 breese Exp $
+ *
+ * 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: trionan.c,v 1.26 2002/12/08 12:08:21 breese Exp $";
+
+#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) || defined(TRIO_COMPILER_BCB)
+ /*
+ * Microsoft Visual C++ and Borland C++ Builder have an _isnan()
+ * function.
+ */
+ return _isnan(number) ? TRIO_TRUE : TRIO_FALSE;
+
+#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) || defined(TRIO_COMPILER_BCB)
+ /*
+ * Microsoft Visual C++ and Borland C++ Builder have 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) || defined(TRIO_COMPILER_BCB)
+ /*
+ * Microsoft Visual C++ and Borland C++ Builder use _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;
+ }
+
+#else
+# if defined(TRIO_COMPILER_DECC)
+ /*
+ * DECC has an fp_class() function.
+ */
+# define TRIO_FPCLASSIFY(n) fp_class(n)
+# define TRIO_QUIET_NAN FP_QNAN
+# define TRIO_SIGNALLING_NAN FP_SNAN
+# define TRIO_POSITIVE_INFINITY FP_POS_INF
+# define TRIO_NEGATIVE_INFINITY FP_NEG_INF
+# define TRIO_POSITIVE_SUBNORMAL FP_POS_DENORM
+# define TRIO_NEGATIVE_SUBNORMAL FP_NEG_DENORM
+# define TRIO_POSITIVE_ZERO FP_POS_ZERO
+# define TRIO_NEGATIVE_ZERO FP_NEG_ZERO
+# define TRIO_POSITIVE_NORMAL FP_POS_NORM
+# define TRIO_NEGATIVE_NORMAL FP_NEG_NORM
+
+# elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB)
+ /*
+ * Microsoft Visual C++ and Borland C++ Builder have an _fpclass()
+ * function.
+ */
+# define TRIO_FPCLASSIFY(n) _fpclass(n)
+# define TRIO_QUIET_NAN _FPCLASS_QNAN
+# define TRIO_SIGNALLING_NAN _FPCLASS_SNAN
+# define TRIO_POSITIVE_INFINITY _FPCLASS_PINF
+# define TRIO_NEGATIVE_INFINITY _FPCLASS_NINF
+# define TRIO_POSITIVE_SUBNORMAL _FPCLASS_PD
+# define TRIO_NEGATIVE_SUBNORMAL _FPCLASS_ND
+# define TRIO_POSITIVE_ZERO _FPCLASS_PZ
+# define TRIO_NEGATIVE_ZERO _FPCLASS_NZ
+# define TRIO_POSITIVE_NORMAL _FPCLASS_PN
+# define TRIO_NEGATIVE_NORMAL _FPCLASS_NN
+
+# 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 TRIO_FPCLASSIFY(n) _class(n)
+# else
+# define TRIO_FPCLASSIFY(n) class(n)
+# endif
+# else
+# define TRIO_FPCLASSIFY(n) fpclassify(n)
+# endif
+# define TRIO_QUIET_NAN FP_QNAN
+# define TRIO_SIGNALLING_NAN FP_SNAN
+# define TRIO_POSITIVE_INFINITY FP_PLUS_INF
+# define TRIO_NEGATIVE_INFINITY FP_MINUS_INF
+# define TRIO_POSITIVE_SUBNORMAL FP_PLUS_DENORM
+# define TRIO_NEGATIVE_SUBNORMAL FP_MINUS_DENORM
+# define TRIO_POSITIVE_ZERO FP_PLUS_ZERO
+# define TRIO_NEGATIVE_ZERO FP_MINUS_ZERO
+# define TRIO_POSITIVE_NORMAL FP_PLUS_NORM
+# define TRIO_NEGATIVE_NORMAL FP_MINUS_NORM
+# endif
+
+# if defined(TRIO_FPCLASSIFY)
+ switch (TRIO_FPCLASSIFY(number)) {
+ case TRIO_QUIET_NAN:
+ case TRIO_SIGNALLING_NAN:
+ *is_negative = TRIO_FALSE; /* NaN has no sign */
+ return TRIO_FP_NAN;
+ case TRIO_POSITIVE_INFINITY:
+ *is_negative = TRIO_FALSE;
+ return TRIO_FP_INFINITE;
+ case TRIO_NEGATIVE_INFINITY:
+ *is_negative = TRIO_TRUE;
+ return TRIO_FP_INFINITE;
+ case TRIO_POSITIVE_SUBNORMAL:
+ *is_negative = TRIO_FALSE;
+ return TRIO_FP_SUBNORMAL;
+ case TRIO_NEGATIVE_SUBNORMAL:
+ *is_negative = TRIO_TRUE;
+ return TRIO_FP_SUBNORMAL;
+ case TRIO_POSITIVE_ZERO:
+ *is_negative = TRIO_FALSE;
+ return TRIO_FP_ZERO;
+ case TRIO_NEGATIVE_ZERO:
+ *is_negative = TRIO_TRUE;
+ return TRIO_FP_ZERO;
+ case TRIO_POSITIVE_NORMAL:
+ *is_negative = TRIO_FALSE;
+ return TRIO_FP_NORMAL;
+ case TRIO_NEGATIVE_NORMAL:
+ *is_negative = TRIO_TRUE;
+ return TRIO_FP_NORMAL;
+ default:
+ /* Just in case... */
+ *is_negative = (number < 0.0);
+ return TRIO_FP_NORMAL;
+ }
+
+# 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
+#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
diff --git a/trio/trionan.h b/trio/trionan.h
new file mode 100644
index 00000000..3fbed375
--- /dev/null
+++ b/trio/trionan.h
@@ -0,0 +1,81 @@
+/*************************************************************************
+ *
+ * $Id: trionan.h,v 1.7 2002/05/04 14:26:44 breese Exp $
+ *
+ * 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 */
diff --git a/trio/triop.h b/trio/triop.h
new file mode 100644
index 00000000..a0132528
--- /dev/null
+++ b/trio/triop.h
@@ -0,0 +1,150 @@
+/*************************************************************************
+ *
+ * $Id: triop.h,v 1.12 2002/06/23 11:58:06 breese Exp $
+ *
+ * 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 */
diff --git a/trio/triostr.c b/trio/triostr.c
new file mode 100644
index 00000000..199429e4
--- /dev/null
+++ b/trio/triostr.c
@@ -0,0 +1,2102 @@
+/*************************************************************************
+ *
+ * $Id: triostr.c,v 1.19 2003/03/01 15:34:02 breese Exp $
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+/*************************************************************************
+ * Include files
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+#include "triodef.h"
+#include "triostr.h"
+
+/*************************************************************************
+ * Definitions
+ */
+
+#if !defined(TRIO_STRING_PUBLIC)
+# define TRIO_STRING_PUBLIC TRIO_PUBLIC
+#endif
+#if !defined(TRIO_STRING_PRIVATE)
+# define TRIO_STRING_PRIVATE TRIO_PRIVATE
+#endif
+
+#if !defined(NULL)
+# define NULL 0
+#endif
+#if !defined(NIL)
+# define NIL ((char)0)
+#endif
+#if !defined(FALSE)
+# define FALSE (1 == 0)
+# define TRUE (! FALSE)
+#endif
+#if !defined(BOOLEAN_T)
+# define BOOLEAN_T int
+#endif
+
+#if defined(TRIO_COMPILER_SUPPORTS_C99)
+# define USE_STRTOD
+# define USE_STRTOF
+#elif defined(TRIO_COMPILER_MSVC)
+# define USE_STRTOD
+#endif
+
+#if defined(TRIO_PLATFORM_UNIX)
+# define USE_STRCASECMP
+# define USE_STRNCASECMP
+# if defined(TRIO_PLATFORM_SUNOS)
+# define USE_SYS_ERRLIST
+# else
+# define USE_STRERROR
+# endif
+# if defined(TRIO_PLATFORM_QNX)
+# define strcasecmp(x,y) stricmp(x,y)
+# define strncasecmp(x,y,n) strnicmp(x,y,n)
+# endif
+#elif defined(TRIO_PLATFORM_WIN32)
+# define USE_STRCASECMP
+# define strcasecmp(x,y) strcmpi(x,y)
+#endif
+
+#if !(defined(TRIO_PLATFORM_SUNOS))
+# define USE_TOLOWER
+# define USE_TOUPPER
+#endif
+
+/*************************************************************************
+ * Structures
+ */
+
+struct _trio_string_t
+{
+ char *content;
+ size_t length;
+ size_t allocated;
+};
+
+/*************************************************************************
+ * Constants
+ */
+
+#if !defined(TRIO_MINIMAL)
+static TRIO_CONST char rcsid[] = "@(#)$Id: triostr.c,v 1.19 2003/03/01 15:34:02 breese Exp $";
+#endif
+
+/*************************************************************************
+ * Static String Functions
+ */
+
+#if defined(TRIO_DOCUMENTATION)
+# include "doc/doc_static.h"
+#endif
+/** @addtogroup StaticStrings
+ @{
+*/
+
+/**
+ Create new string.
+
+ @param size Size of new string.
+ @return Pointer to string, or NULL if allocation failed.
+*/
+TRIO_STRING_PUBLIC char *
+trio_create
+TRIO_ARGS1((size),
+ size_t size)
+{
+ return (char *)TRIO_MALLOC(size);
+}
+
+
+/**
+ Destroy string.
+
+ @param string String to be freed.
+*/
+TRIO_STRING_PUBLIC void
+trio_destroy
+TRIO_ARGS1((string),
+ char *string)
+{
+ if (string)
+ {
+ TRIO_FREE(string);
+ }
+}
+
+
+/**
+ Count the number of characters in a string.
+
+ @param string String to measure.
+ @return Number of characters in @string.
+*/
+TRIO_STRING_PUBLIC size_t
+trio_length
+TRIO_ARGS1((string),
+ TRIO_CONST char *string)
+{
+ return strlen(string);
+}
+
+
+#if !defined(TRIO_MINIMAL)
+/**
+ Append @p source at the end of @p target.
+
+ @param target Target string.
+ @param source Source string.
+ @return Boolean value indicating success or failure.
+
+ @pre @p target must point to a memory chunk with sufficient room to
+ contain the @p target string and @p source string.
+ @pre No boundary checking is performed, so insufficient memory will
+ result in a buffer overrun.
+ @post @p target will be zero terminated.
+*/
+TRIO_STRING_PUBLIC int
+trio_append
+TRIO_ARGS2((target, source),
+ char *target,
+ TRIO_CONST char *source)
+{
+ assert(target);
+ assert(source);
+
+ return (strcat(target, source) != NULL);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+#if !defined(TRIO_MINIMAL)
+/**
+ Append at most @p max characters from @p source to @p target.
+
+ @param target Target string.
+ @param max Maximum number of characters to append.
+ @param source Source string.
+ @return Boolean value indicating success or failure.
+
+ @pre @p target must point to a memory chuck with sufficient room to
+ contain the @p target string and the @p source string (at most @p max
+ characters).
+ @pre No boundary checking is performed, so insufficient memory will
+ result in a buffer overrun.
+ @post @p target will be zero terminated.
+*/
+TRIO_STRING_PUBLIC int
+trio_append_max
+TRIO_ARGS3((target, max, source),
+ char *target,
+ size_t max,
+ TRIO_CONST char *source)
+{
+ size_t length;
+
+ assert(target);
+ assert(source);
+
+ length = trio_length(target);
+
+ if (max > length)
+ {
+ strncat(target, source, max - length - 1);
+ }
+ return TRUE;
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/**
+ Determine if a string contains a substring.
+
+ @param string String to be searched.
+ @param substring String to be found.
+ @return Boolean value indicating success or failure.
+*/
+TRIO_STRING_PUBLIC int
+trio_contains
+TRIO_ARGS2((string, substring),
+ TRIO_CONST char *string,
+ TRIO_CONST char *substring)
+{
+ assert(string);
+ assert(substring);
+
+ return (0 != strstr(string, substring));
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/**
+ Copy @p source to @p target.
+
+ @param target Target string.
+ @param source Source string.
+ @return Boolean value indicating success or failure.
+
+ @pre @p target must point to a memory chunk with sufficient room to
+ contain the @p source string.
+ @pre No boundary checking is performed, so insufficient memory will
+ result in a buffer overrun.
+ @post @p target will be zero terminated.
+*/
+TRIO_STRING_PUBLIC int
+trio_copy
+TRIO_ARGS2((target, source),
+ char *target,
+ TRIO_CONST char *source)
+{
+ assert(target);
+ assert(source);
+
+ (void)strcpy(target, source);
+ return TRUE;
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+/**
+ Copy at most @p max characters from @p source to @p target.
+
+ @param target Target string.
+ @param max Maximum number of characters to append.
+ @param source Source string.
+ @return Boolean value indicating success or failure.
+
+ @pre @p target must point to a memory chunk with sufficient room to
+ contain the @p source string (at most @p max characters).
+ @pre No boundary checking is performed, so insufficient memory will
+ result in a buffer overrun.
+ @post @p target will be zero terminated.
+*/
+TRIO_STRING_PUBLIC int
+trio_copy_max
+TRIO_ARGS3((target, max, source),
+ char *target,
+ size_t max,
+ TRIO_CONST char *source)
+{
+ assert(target);
+ assert(source);
+ assert(max > 0); /* Includes != 0 */
+
+ (void)strncpy(target, source, max - 1);
+ target[max - 1] = (char)0;
+ return TRUE;
+}
+
+
+/*
+ * TrioDuplicateMax
+ */
+TRIO_STRING_PRIVATE char *
+TrioDuplicateMax
+TRIO_ARGS2((source, size),
+ TRIO_CONST char *source,
+ size_t size)
+{
+ char *target;
+
+ assert(source);
+
+ /* Make room for string plus a terminating zero */
+ size++;
+ target = trio_create(size);
+ if (target)
+ {
+ trio_copy_max(target, size, source);
+ }
+ return target;
+}
+
+
+/**
+ Duplicate @p source.
+
+ @param source Source string.
+ @return A copy of the @p source string.
+
+ @post @p target will be zero terminated.
+*/
+TRIO_STRING_PUBLIC char *
+trio_duplicate
+TRIO_ARGS1((source),
+ TRIO_CONST char *source)
+{
+ return TrioDuplicateMax(source, trio_length(source));
+}
+
+
+#if !defined(TRIO_MINIMAL)
+/**
+ Duplicate at most @p max characters of @p source.
+
+ @param source Source string.
+ @param max Maximum number of characters to duplicate.
+ @return A copy of the @p source string.
+
+ @post @p target will be zero terminated.
+*/
+TRIO_STRING_PUBLIC char *
+trio_duplicate_max TRIO_ARGS2((source, max),
+ TRIO_CONST char *source,
+ size_t max)
+{
+ size_t length;
+
+ assert(source);
+ assert(max > 0);
+
+ length = trio_length(source);
+ if (length > max)
+ {
+ length = max;
+ }
+ return TrioDuplicateMax(source, length);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+/**
+ Compare if two strings are equal.
+
+ @param first First string.
+ @param second Second string.
+ @return Boolean indicating whether the two strings are equal or not.
+
+ Case-insensitive comparison.
+*/
+TRIO_STRING_PUBLIC int
+trio_equal
+TRIO_ARGS2((first, second),
+ TRIO_CONST char *first,
+ TRIO_CONST char *second)
+{
+ assert(first);
+ assert(second);
+
+ if ((first != NULL) && (second != NULL))
+ {
+#if defined(USE_STRCASECMP)
+ return (0 == strcasecmp(first, second));
+#else
+ while ((*first != NIL) && (*second != NIL))
+ {
+ if (trio_to_upper(*first) != trio_to_upper(*second))
+ {
+ break;
+ }
+ first++;
+ second++;
+ }
+ return ((*first == NIL) && (*second == NIL));
+#endif
+ }
+ return FALSE;
+}
+
+
+/**
+ Compare if two strings are equal.
+
+ @param first First string.
+ @param second Second string.
+ @return Boolean indicating whether the two strings are equal or not.
+
+ Case-sensitive comparison.
+*/
+TRIO_STRING_PUBLIC int
+trio_equal_case
+TRIO_ARGS2((first, second),
+ TRIO_CONST char *first,
+ TRIO_CONST char *second)
+{
+ assert(first);
+ assert(second);
+
+ if ((first != NULL) && (second != NULL))
+ {
+ return (0 == strcmp(first, second));
+ }
+ return FALSE;
+}
+
+
+#if !defined(TRIO_MINIMAL)
+/**
+ Compare if two strings up until the first @p max characters are equal.
+
+ @param first First string.
+ @param max Maximum number of characters to compare.
+ @param second Second string.
+ @return Boolean indicating whether the two strings are equal or not.
+
+ Case-sensitive comparison.
+*/
+TRIO_STRING_PUBLIC int
+trio_equal_case_max
+TRIO_ARGS3((first, max, second),
+ TRIO_CONST char *first,
+ size_t max,
+ TRIO_CONST char *second)
+{
+ assert(first);
+ assert(second);
+
+ if ((first != NULL) && (second != NULL))
+ {
+ return (0 == strncmp(first, second, max));
+ }
+ return FALSE;
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+/**
+ Compare if two strings are equal.
+
+ @param first First string.
+ @param second Second string.
+ @return Boolean indicating whether the two strings are equal or not.
+
+ Collating characters are considered equal.
+*/
+TRIO_STRING_PUBLIC int
+trio_equal_locale
+TRIO_ARGS2((first, second),
+ TRIO_CONST char *first,
+ TRIO_CONST char *second)
+{
+ assert(first);
+ assert(second);
+
+#if defined(LC_COLLATE)
+ return (strcoll(first, second) == 0);
+#else
+ return trio_equal(first, second);
+#endif
+}
+
+
+/**
+ Compare if two strings up until the first @p max characters are equal.
+
+ @param first First string.
+ @param max Maximum number of characters to compare.
+ @param second Second string.
+ @return Boolean indicating whether the two strings are equal or not.
+
+ Case-insensitive comparison.
+*/
+TRIO_STRING_PUBLIC int
+trio_equal_max
+TRIO_ARGS3((first, max, second),
+ TRIO_CONST char *first,
+ size_t max,
+ TRIO_CONST char *second)
+{
+ assert(first);
+ assert(second);
+
+ if ((first != NULL) && (second != NULL))
+ {
+#if defined(USE_STRNCASECMP)
+ return (0 == strncasecmp(first, second, max));
+#else
+ /* Not adequately tested yet */
+ size_t cnt = 0;
+ while ((*first != NIL) && (*second != NIL) && (cnt <= max))
+ {
+ if (trio_to_upper(*first) != trio_to_upper(*second))
+ {
+ break;
+ }
+ first++;
+ second++;
+ cnt++;
+ }
+ return ((cnt == max) || ((*first == NIL) && (*second == NIL)));
+#endif
+ }
+ return FALSE;
+}
+
+
+/**
+ Provide a textual description of an error code (errno).
+
+ @param error_number Error number.
+ @return Textual description of @p error_number.
+*/
+TRIO_STRING_PUBLIC TRIO_CONST char *
+trio_error
+TRIO_ARGS1((error_number),
+ int error_number)
+{
+#if defined(USE_STRERROR)
+
+ return strerror(error_number);
+
+#elif defined(USE_SYS_ERRLIST)
+
+ extern char *sys_errlist[];
+ extern int sys_nerr;
+
+ return ((error_number < 0) || (error_number >= sys_nerr))
+ ? "unknown"
+ : sys_errlist[error_number];
+
+#else
+
+ return "unknown";
+
+#endif
+}
+
+
+#if !defined(TRIO_MINIMAL)
+/**
+ Format the date/time according to @p format.
+
+ @param target Target string.
+ @param max Maximum number of characters to format.
+ @param format Formatting string.
+ @param datetime Date/time structure.
+ @return Number of formatted characters.
+
+ The formatting string accepts the same specifiers as the standard C
+ function strftime.
+*/
+TRIO_STRING_PUBLIC size_t
+trio_format_date_max
+TRIO_ARGS4((target, max, format, datetime),
+ char *target,
+ size_t max,
+ TRIO_CONST char *format,
+ TRIO_CONST struct tm *datetime)
+{
+ assert(target);
+ assert(format);
+ assert(datetime);
+ assert(max > 0);
+
+ return strftime(target, max, format, datetime);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/**
+ Calculate a hash value for a string.
+
+ @param string String to be calculated on.
+ @param type Hash function.
+ @return Calculated hash value.
+
+ @p type can be one of the following
+ @li @c TRIO_HASH_PLAIN Plain hash function.
+*/
+TRIO_STRING_PUBLIC unsigned long
+trio_hash
+TRIO_ARGS2((string, type),
+ TRIO_CONST char *string,
+ int type)
+{
+ unsigned long value = 0L;
+ char ch;
+
+ assert(string);
+
+ switch (type)
+ {
+ case TRIO_HASH_PLAIN:
+ while ( (ch = *string++) != NIL )
+ {
+ value *= 31;
+ value += (unsigned long)ch;
+ }
+ break;
+ default:
+ assert(FALSE);
+ break;
+ }
+ return value;
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/**
+ Find first occurrence of a character in a string.
+
+ @param string String to be searched.
+ @param character Character to be found.
+ @param A pointer to the found character, or NULL if character was not found.
+ */
+TRIO_STRING_PUBLIC char *
+trio_index
+TRIO_ARGS2((string, character),
+ TRIO_CONST char *string,
+ int character)
+{
+ assert(string);
+
+ return strchr(string, character);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/**
+ Find last occurrence of a character in a string.
+
+ @param string String to be searched.
+ @param character Character to be found.
+ @param A pointer to the found character, or NULL if character was not found.
+ */
+TRIO_STRING_PUBLIC char *
+trio_index_last
+TRIO_ARGS2((string, character),
+ TRIO_CONST char *string,
+ int character)
+{
+ assert(string);
+
+ return strchr(string, character);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/**
+ Convert the alphabetic letters in the string to lower-case.
+
+ @param target String to be converted.
+ @return Number of processed characters (converted or not).
+*/
+TRIO_STRING_PUBLIC int
+trio_lower
+TRIO_ARGS1((target),
+ char *target)
+{
+ assert(target);
+
+ return trio_span_function(target, target, trio_to_lower);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/**
+ Compare two strings using wildcards.
+
+ @param string String to be searched.
+ @param pattern Pattern, including wildcards, to search for.
+ @return Boolean value indicating success or failure.
+
+ Case-insensitive comparison.
+
+ The following wildcards can be used
+ @li @c * Match any number of characters.
+ @li @c ? Match a single character.
+*/
+TRIO_STRING_PUBLIC int
+trio_match
+TRIO_ARGS2((string, pattern),
+ TRIO_CONST char *string,
+ TRIO_CONST char *pattern)
+{
+ assert(string);
+ assert(pattern);
+
+ for (; ('*' != *pattern); ++pattern, ++string)
+ {
+ if (NIL == *string)
+ {
+ return (NIL == *pattern);
+ }
+ if ((trio_to_upper((int)*string) != trio_to_upper((int)*pattern))
+ && ('?' != *pattern))
+ {
+ return FALSE;
+ }
+ }
+ /* two-line patch to prevent *too* much recursiveness: */
+ while ('*' == pattern[1])
+ pattern++;
+
+ do
+ {
+ if ( trio_match(string, &pattern[1]) )
+ {
+ return TRUE;
+ }
+ }
+ while (*string++);
+
+ return FALSE;
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/**
+ Compare two strings using wildcards.
+
+ @param string String to be searched.
+ @param pattern Pattern, including wildcards, to search for.
+ @return Boolean value indicating success or failure.
+
+ Case-sensitive comparison.
+
+ The following wildcards can be used
+ @li @c * Match any number of characters.
+ @li @c ? Match a single character.
+*/
+TRIO_STRING_PUBLIC int
+trio_match_case
+TRIO_ARGS2((string, pattern),
+ TRIO_CONST char *string,
+ TRIO_CONST char *pattern)
+{
+ assert(string);
+ assert(pattern);
+
+ for (; ('*' != *pattern); ++pattern, ++string)
+ {
+ if (NIL == *string)
+ {
+ return (NIL == *pattern);
+ }
+ if ((*string != *pattern)
+ && ('?' != *pattern))
+ {
+ return FALSE;
+ }
+ }
+ /* two-line patch to prevent *too* much recursiveness: */
+ while ('*' == pattern[1])
+ pattern++;
+
+ do
+ {
+ if ( trio_match_case(string, &pattern[1]) )
+ {
+ return TRUE;
+ }
+ }
+ while (*string++);
+
+ return FALSE;
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/**
+ Execute a function on each character in string.
+
+ @param target Target string.
+ @param source Source string.
+ @param Function Function to be executed.
+ @return Number of processed characters.
+*/
+TRIO_STRING_PUBLIC size_t
+trio_span_function
+TRIO_ARGS3((target, source, Function),
+ char *target,
+ TRIO_CONST char *source,
+ int (*Function) TRIO_PROTO((int)))
+{
+ size_t count = 0;
+
+ assert(target);
+ assert(source);
+ assert(Function);
+
+ while (*source != NIL)
+ {
+ *target++ = Function(*source++);
+ count++;
+ }
+ return count;
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/**
+ Search for a substring in a string.
+
+ @param string String to be searched.
+ @param substring String to be found.
+ @return Pointer to first occurrence of @p substring in @p string, or NULL
+ if no match was found.
+*/
+TRIO_STRING_PUBLIC char *
+trio_substring
+TRIO_ARGS2((string, substring),
+ TRIO_CONST char *string,
+ TRIO_CONST char *substring)
+{
+ assert(string);
+ assert(substring);
+
+ return strstr(string, substring);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/**
+ Search for a substring in the first @p max characters of a string.
+
+ @param string String to be searched.
+ @param max Maximum characters to be searched.
+ @param substring String to be found.
+ @return Pointer to first occurrence of @p substring in @p string, or NULL
+ if no match was found.
+*/
+TRIO_STRING_PUBLIC char *
+trio_substring_max
+TRIO_ARGS3((string, max, substring),
+ TRIO_CONST char *string,
+ size_t max,
+ TRIO_CONST char *substring)
+{
+ size_t count;
+ size_t size;
+ char *result = NULL;
+
+ assert(string);
+ assert(substring);
+
+ size = trio_length(substring);
+ if (size <= max)
+ {
+ for (count = 0; count <= max - size; count++)
+ {
+ if (trio_equal_max(substring, size, &string[count]))
+ {
+ result = (char *)&string[count];
+ break;
+ }
+ }
+ }
+ return result;
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/**
+ Tokenize string.
+
+ @param string String to be tokenized.
+ @param tokens String containing list of delimiting characters.
+ @return Start of new token.
+
+ @warning @p string will be destroyed.
+*/
+TRIO_STRING_PUBLIC char *
+trio_tokenize
+TRIO_ARGS2((string, delimiters),
+ char *string,
+ TRIO_CONST char *delimiters)
+{
+ assert(delimiters);
+
+ return strtok(string, delimiters);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+/**
+ Convert string to floating-point number.
+
+ @param source String to be converted.
+ @param endp Pointer to end of the converted string.
+ @return A floating-point number.
+
+ The following Extended Backus-Naur form is used
+ @verbatim
+ double ::= [ <sign> ]
+ ( <number> |
+ <number> <decimal_point> <number> |
+ <decimal_point> <number> )
+ [ <exponential> [ <sign> ] <number> ]
+ number ::= 1*( <digit> )
+ digit ::= ( '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' )
+ exponential ::= ( 'e' | 'E' )
+ sign ::= ( '-' | '+' )
+ decimal_point ::= '.'
+ @endverbatim
+*/
+/* FIXME: Add EBNF for hex-floats */
+TRIO_STRING_PUBLIC trio_long_double_t
+trio_to_long_double
+TRIO_ARGS2((source, endp),
+ TRIO_CONST char *source,
+ char **endp)
+{
+#if defined(USE_STRTOLD)
+ return strtold(source, endp);
+#else
+ int isNegative = FALSE;
+ int isExponentNegative = FALSE;
+ trio_long_double_t integer = 0.0;
+ trio_long_double_t fraction = 0.0;
+ unsigned long exponent = 0;
+ trio_long_double_t base;
+ trio_long_double_t fracdiv = 1.0;
+ trio_long_double_t value = 0.0;
+
+ /* First try hex-floats */
+ if ((source[0] == '0') && ((source[1] == 'x') || (source[1] == 'X')))
+ {
+ base = 16.0;
+ source += 2;
+ while (isxdigit((int)*source))
+ {
+ integer *= base;
+ integer += (isdigit((int)*source)
+ ? (*source - '0')
+ : 10 + (trio_to_upper((int)*source) - 'A'));
+ source++;
+ }
+ if (*source == '.')
+ {
+ source++;
+ while (isxdigit((int)*source))
+ {
+ fracdiv /= base;
+ fraction += fracdiv * (isdigit((int)*source)
+ ? (*source - '0')
+ : 10 + (trio_to_upper((int)*source) - 'A'));
+ source++;
+ }
+ if ((*source == 'p') || (*source == 'P'))
+ {
+ source++;
+ if ((*source == '+') || (*source == '-'))
+ {
+ isExponentNegative = (*source == '-');
+ source++;
+ }
+ while (isdigit((int)*source))
+ {
+ exponent *= 10;
+ exponent += (*source - '0');
+ source++;
+ }
+ }
+ }
+ /* For later use with exponent */
+ base = 2.0;
+ }
+ else /* Then try normal decimal floats */
+ {
+ base = 10.0;
+ isNegative = (*source == '-');
+ /* Skip sign */
+ if ((*source == '+') || (*source == '-'))
+ source++;
+
+ /* Integer part */
+ while (isdigit((int)*source))
+ {
+ integer *= base;
+ integer += (*source - '0');
+ source++;
+ }
+
+ if (*source == '.')
+ {
+ source++; /* skip decimal point */
+ while (isdigit((int)*source))
+ {
+ fracdiv /= base;
+ fraction += (*source - '0') * fracdiv;
+ source++;
+ }
+ }
+ if ((*source == 'e')
+ || (*source == 'E')
+#if TRIO_MICROSOFT
+ || (*source == 'd')
+ || (*source == 'D')
+#endif
+ )
+ {
+ source++; /* Skip exponential indicator */
+ isExponentNegative = (*source == '-');
+ if ((*source == '+') || (*source == '-'))
+ source++;
+ while (isdigit((int)*source))
+ {
+ exponent *= (int)base;
+ exponent += (*source - '0');
+ source++;
+ }
+ }
+ }
+
+ value = integer + fraction;
+ if (exponent != 0)
+ {
+ if (isExponentNegative)
+ value /= pow(base, (double)exponent);
+ else
+ value *= pow(base, (double)exponent);
+ }
+ if (isNegative)
+ value = -value;
+
+ if (endp)
+ *endp = (char *)source;
+ return value;
+#endif
+}
+
+
+/**
+ Convert string to floating-point number.
+
+ @param source String to be converted.
+ @param endp Pointer to end of the converted string.
+ @return A floating-point number.
+
+ See @ref trio_to_long_double.
+*/
+TRIO_STRING_PUBLIC double
+trio_to_double
+TRIO_ARGS2((source, endp),
+ TRIO_CONST char *source,
+ char **endp)
+{
+#if defined(USE_STRTOD)
+ return strtod(source, endp);
+#else
+ return (double)trio_to_long_double(source, endp);
+#endif
+}
+
+#if !defined(TRIO_MINIMAL)
+/**
+ Convert string to floating-point number.
+
+ @param source String to be converted.
+ @param endp Pointer to end of the converted string.
+ @return A floating-point number.
+
+ See @ref trio_to_long_double.
+*/
+TRIO_STRING_PUBLIC float
+trio_to_float
+TRIO_ARGS2((source, endp),
+ TRIO_CONST char *source,
+ char **endp)
+{
+#if defined(USE_STRTOF)
+ return strtof(source, endp);
+#else
+ return (float)trio_to_long_double(source, endp);
+#endif
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+/**
+ Convert string to signed integer.
+
+ @param string String to be converted.
+ @param endp Pointer to end of converted string.
+ @param base Radix number of number.
+*/
+TRIO_STRING_PUBLIC long
+trio_to_long
+TRIO_ARGS3((string, endp, base),
+ TRIO_CONST char *string,
+ char **endp,
+ int base)
+{
+ assert(string);
+ assert((base >= 2) && (base <= 36));
+
+ return strtol(string, endp, base);
+}
+
+
+#if !defined(TRIO_MINIMAL)
+/**
+ Convert one alphabetic letter to lower-case.
+
+ @param source The letter to be converted.
+ @return The converted letter.
+*/
+TRIO_STRING_PUBLIC int
+trio_to_lower
+TRIO_ARGS1((source),
+ int source)
+{
+#if defined(USE_TOLOWER)
+
+ return tolower(source);
+
+#else
+
+ /* Does not handle locales or non-contiguous alphabetic characters */
+ return ((source >= (int)'A') && (source <= (int)'Z'))
+ ? source - 'A' + 'a'
+ : source;
+
+#endif
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+#if !defined(TRIO_MINIMAL)
+/**
+ Convert string to unsigned integer.
+
+ @param string String to be converted.
+ @param endp Pointer to end of converted string.
+ @param base Radix number of number.
+*/
+TRIO_STRING_PUBLIC unsigned long
+trio_to_unsigned_long
+TRIO_ARGS3((string, endp, base),
+ TRIO_CONST char *string,
+ char **endp,
+ int base)
+{
+ assert(string);
+ assert((base >= 2) && (base <= 36));
+
+ return strtoul(string, endp, base);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+/**
+ Convert one alphabetic letter to upper-case.
+
+ @param source The letter to be converted.
+ @return The converted letter.
+*/
+TRIO_STRING_PUBLIC int
+trio_to_upper
+TRIO_ARGS1((source),
+ int source)
+{
+#if defined(USE_TOUPPER)
+
+ return toupper(source);
+
+#else
+
+ /* Does not handle locales or non-contiguous alphabetic characters */
+ return ((source >= (int)'a') && (source <= (int)'z'))
+ ? source - 'a' + 'A'
+ : source;
+
+#endif
+}
+
+#if !defined(TRIO_MINIMAL)
+/**
+ Convert the alphabetic letters in the string to upper-case.
+
+ @param target The string to be converted.
+ @return The number of processed characters (converted or not).
+*/
+TRIO_STRING_PUBLIC int
+trio_upper
+TRIO_ARGS1((target),
+ char *target)
+{
+ assert(target);
+
+ return trio_span_function(target, target, trio_to_upper);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+/** @} End of StaticStrings */
+
+
+/*************************************************************************
+ * Dynamic String Functions
+ */
+
+#if defined(TRIO_DOCUMENTATION)
+# include "doc/doc_dynamic.h"
+#endif
+/** @addtogroup DynamicStrings
+ @{
+*/
+
+/*
+ * TrioStringAlloc
+ */
+TRIO_STRING_PRIVATE trio_string_t *
+TrioStringAlloc(TRIO_NOARGS)
+{
+ trio_string_t *self;
+
+ self = (trio_string_t *)TRIO_MALLOC(sizeof(trio_string_t));
+ if (self)
+ {
+ self->content = NULL;
+ self->length = 0;
+ self->allocated = 0;
+ }
+ return self;
+}
+
+
+/*
+ * TrioStringGrow
+ *
+ * The size of the string will be increased by 'delta' characters. If
+ * 'delta' is zero, the size will be doubled.
+ */
+TRIO_STRING_PRIVATE BOOLEAN_T
+TrioStringGrow
+TRIO_ARGS2((self, delta),
+ trio_string_t *self,
+ size_t delta)
+{
+ BOOLEAN_T status = FALSE;
+ char *new_content;
+ size_t new_size;
+
+ new_size = (delta == 0)
+ ? ( (self->allocated == 0) ? 1 : self->allocated * 2 )
+ : self->allocated + delta;
+
+ new_content = (char *)TRIO_REALLOC(self->content, new_size);
+ if (new_content)
+ {
+ self->content = new_content;
+ self->allocated = new_size;
+ status = TRUE;
+ }
+ return status;
+}
+
+
+#if !defined(TRIO_MINIMAL)
+/*
+ * TrioStringGrowTo
+ *
+ * The size of the string will be increased to 'length' plus one characters.
+ * If 'length' is less than the original size, the original size will be
+ * used (that is, the size of the string is never decreased).
+ */
+TRIO_STRING_PRIVATE BOOLEAN_T
+TrioStringGrowTo
+TRIO_ARGS2((self, length),
+ trio_string_t *self,
+ size_t length)
+{
+ length++; /* Room for terminating zero */
+ return (self->allocated < length)
+ ? TrioStringGrow(self, length - self->allocated)
+ : TRUE;
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/**
+ Create a new dynamic string.
+
+ @param initial_size Initial size of the buffer.
+ @return Newly allocated dynamic string, or NULL if memory allocation failed.
+*/
+TRIO_STRING_PUBLIC trio_string_t *
+trio_string_create
+TRIO_ARGS1((initial_size),
+ int initial_size)
+{
+ trio_string_t *self;
+
+ self = TrioStringAlloc();
+ if (self)
+ {
+ if (TrioStringGrow(self,
+ (size_t)((initial_size > 0) ? initial_size : 1)))
+ {
+ self->content[0] = (char)0;
+ self->allocated = initial_size;
+ }
+ else
+ {
+ trio_string_destroy(self);
+ self = NULL;
+ }
+ }
+ return self;
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+/**
+ Deallocate the dynamic string and its contents.
+
+ @param self Dynamic string
+*/
+TRIO_STRING_PUBLIC void
+trio_string_destroy
+TRIO_ARGS1((self),
+ trio_string_t *self)
+{
+ assert(self);
+
+ if (self)
+ {
+ trio_destroy(self->content);
+ TRIO_FREE(self);
+ }
+}
+
+
+#if !defined(TRIO_MINIMAL)
+/**
+ Get a pointer to the content.
+
+ @param self Dynamic string.
+ @param offset Offset into content.
+ @return Pointer to the content.
+
+ @p Offset can be zero, positive, or negative. If @p offset is zero,
+ then the start of the content will be returned. If @p offset is positive,
+ then a pointer to @p offset number of characters from the beginning of the
+ content is returned. If @p offset is negative, then a pointer to @p offset
+ number of characters from the ending of the string, starting at the
+ terminating zero, is returned.
+*/
+TRIO_STRING_PUBLIC char *
+trio_string_get
+TRIO_ARGS2((self, offset),
+ trio_string_t *self,
+ int offset)
+{
+ char *result = NULL;
+
+ assert(self);
+
+ if (self->content != NULL)
+ {
+ if (self->length == 0)
+ {
+ (void)trio_string_length(self);
+ }
+ if (offset >= 0)
+ {
+ if (offset > (int)self->length)
+ {
+ offset = self->length;
+ }
+ }
+ else
+ {
+ offset += self->length + 1;
+ if (offset < 0)
+ {
+ offset = 0;
+ }
+ }
+ result = &(self->content[offset]);
+ }
+ return result;
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+/**
+ Extract the content.
+
+ @param self Dynamic String
+ @return Content of dynamic string.
+
+ The content is removed from the dynamic string. This enables destruction
+ of the dynamic string without deallocation of the content.
+*/
+TRIO_STRING_PUBLIC char *
+trio_string_extract
+TRIO_ARGS1((self),
+ trio_string_t *self)
+{
+ char *result;
+
+ assert(self);
+
+ result = self->content;
+ /* FIXME: Allocate new empty buffer? */
+ self->content = NULL;
+ self->length = self->allocated = 0;
+ return result;
+}
+
+
+#if !defined(TRIO_MINIMAL)
+/**
+ Set the content of the dynamic string.
+
+ @param self Dynamic String
+ @param buffer The new content.
+
+ Sets the content of the dynamic string to a copy @p buffer.
+ An existing content will be deallocated first, if necessary.
+
+ @remark
+ This function will make a copy of @p buffer.
+ You are responsible for deallocating @p buffer yourself.
+*/
+TRIO_STRING_PUBLIC void
+trio_xstring_set
+TRIO_ARGS2((self, buffer),
+ trio_string_t *self,
+ char *buffer)
+{
+ assert(self);
+
+ trio_destroy(self->content);
+ self->content = trio_duplicate(buffer);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+/*
+ * trio_string_size
+ */
+TRIO_STRING_PUBLIC int
+trio_string_size
+TRIO_ARGS1((self),
+ trio_string_t *self)
+{
+ assert(self);
+
+ return self->allocated;
+}
+
+
+/*
+ * trio_string_terminate
+ */
+TRIO_STRING_PUBLIC void
+trio_string_terminate
+TRIO_ARGS1((self),
+ trio_string_t *self)
+{
+ trio_xstring_append_char(self, 0);
+}
+
+
+#if !defined(TRIO_MINIMAL)
+/**
+ Append the second string to the first.
+
+ @param self Dynamic string to be modified.
+ @param other Dynamic string to copy from.
+ @return Boolean value indicating success or failure.
+*/
+TRIO_STRING_PUBLIC int
+trio_string_append
+TRIO_ARGS2((self, other),
+ trio_string_t *self,
+ trio_string_t *other)
+{
+ size_t length;
+
+ assert(self);
+ assert(other);
+
+ length = self->length + other->length;
+ if (!TrioStringGrowTo(self, length))
+ goto error;
+ trio_copy(&self->content[self->length], other->content);
+ self->length = length;
+ return TRUE;
+
+ error:
+ return FALSE;
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/*
+ * trio_xstring_append
+ */
+TRIO_STRING_PUBLIC int
+trio_xstring_append
+TRIO_ARGS2((self, other),
+ trio_string_t *self,
+ TRIO_CONST char *other)
+{
+ size_t length;
+
+ assert(self);
+ assert(other);
+
+ length = self->length + trio_length(other);
+ if (!TrioStringGrowTo(self, length))
+ goto error;
+ trio_copy(&self->content[self->length], other);
+ self->length = length;
+ return TRUE;
+
+ error:
+ return FALSE;
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+/*
+ * trio_xstring_append_char
+ */
+TRIO_STRING_PUBLIC int
+trio_xstring_append_char
+TRIO_ARGS2((self, character),
+ trio_string_t *self,
+ char character)
+{
+ assert(self);
+
+ if ((int)self->length >= trio_string_size(self))
+ {
+ if (!TrioStringGrow(self, 0))
+ goto error;
+ }
+ self->content[self->length] = character;
+ self->length++;
+ return TRUE;
+
+ error:
+ return FALSE;
+}
+
+
+#if !defined(TRIO_MINIMAL)
+/**
+ Search for the first occurrence of second parameter in the first.
+
+ @param self Dynamic string to be modified.
+ @param other Dynamic string to copy from.
+ @return Boolean value indicating success or failure.
+*/
+TRIO_STRING_PUBLIC int
+trio_string_contains
+TRIO_ARGS2((self, other),
+ trio_string_t *self,
+ trio_string_t *other)
+{
+ assert(self);
+ assert(other);
+
+ return trio_contains(self->content, other->content);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/*
+ * trio_xstring_contains
+ */
+TRIO_STRING_PUBLIC int
+trio_xstring_contains
+TRIO_ARGS2((self, other),
+ trio_string_t *self,
+ TRIO_CONST char *other)
+{
+ assert(self);
+ assert(other);
+
+ return trio_contains(self->content, other);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/*
+ * trio_string_copy
+ */
+TRIO_STRING_PUBLIC int
+trio_string_copy
+TRIO_ARGS2((self, other),
+ trio_string_t *self,
+ trio_string_t *other)
+{
+ assert(self);
+ assert(other);
+
+ self->length = 0;
+ return trio_string_append(self, other);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/*
+ * trio_xstring_copy
+ */
+TRIO_STRING_PUBLIC int
+trio_xstring_copy
+TRIO_ARGS2((self, other),
+ trio_string_t *self,
+ TRIO_CONST char *other)
+{
+ assert(self);
+ assert(other);
+
+ self->length = 0;
+ return trio_xstring_append(self, other);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/*
+ * trio_string_duplicate
+ */
+TRIO_STRING_PUBLIC trio_string_t *
+trio_string_duplicate
+TRIO_ARGS1((other),
+ trio_string_t *other)
+{
+ trio_string_t *self;
+
+ assert(other);
+
+ self = TrioStringAlloc();
+ if (self)
+ {
+ self->content = TrioDuplicateMax(other->content, other->length);
+ if (self->content)
+ {
+ self->length = other->length;
+ self->allocated = self->length + 1;
+ }
+ else
+ {
+ self->length = self->allocated = 0;
+ }
+ }
+ return self;
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+/*
+ * trio_xstring_duplicate
+ */
+TRIO_STRING_PUBLIC trio_string_t *
+trio_xstring_duplicate
+TRIO_ARGS1((other),
+ TRIO_CONST char *other)
+{
+ trio_string_t *self;
+
+ assert(other);
+
+ self = TrioStringAlloc();
+ if (self)
+ {
+ self->content = TrioDuplicateMax(other, trio_length(other));
+ if (self->content)
+ {
+ self->length = trio_length(self->content);
+ self->allocated = self->length + 1;
+ }
+ else
+ {
+ self->length = self->allocated = 0;
+ }
+ }
+ return self;
+}
+
+
+#if !defined(TRIO_MINIMAL)
+/*
+ * trio_string_equal
+ */
+TRIO_STRING_PUBLIC int
+trio_string_equal
+TRIO_ARGS2((self, other),
+ trio_string_t *self,
+ trio_string_t *other)
+{
+ assert(self);
+ assert(other);
+
+ return trio_equal(self->content, other->content);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/*
+ * trio_xstring_equal
+ */
+TRIO_STRING_PUBLIC int
+trio_xstring_equal
+TRIO_ARGS2((self, other),
+ trio_string_t *self,
+ TRIO_CONST char *other)
+{
+ assert(self);
+ assert(other);
+
+ return trio_equal(self->content, other);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/*
+ * trio_string_equal_max
+ */
+TRIO_STRING_PUBLIC int
+trio_string_equal_max
+TRIO_ARGS3((self, max, other),
+ trio_string_t *self,
+ size_t max,
+ trio_string_t *other)
+{
+ assert(self);
+ assert(other);
+
+ return trio_equal_max(self->content, max, other->content);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/*
+ * trio_xstring_equal_max
+ */
+TRIO_STRING_PUBLIC int
+trio_xstring_equal_max
+TRIO_ARGS3((self, max, other),
+ trio_string_t *self,
+ size_t max,
+ TRIO_CONST char *other)
+{
+ assert(self);
+ assert(other);
+
+ return trio_equal_max(self->content, max, other);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/*
+ * trio_string_equal_case
+ */
+TRIO_STRING_PUBLIC int
+trio_string_equal_case
+TRIO_ARGS2((self, other),
+ trio_string_t *self,
+ trio_string_t *other)
+{
+ assert(self);
+ assert(other);
+
+ return trio_equal_case(self->content, other->content);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/*
+ * trio_xstring_equal_case
+ */
+TRIO_STRING_PUBLIC int
+trio_xstring_equal_case
+TRIO_ARGS2((self, other),
+ trio_string_t *self,
+ TRIO_CONST char *other)
+{
+ assert(self);
+ assert(other);
+
+ return trio_equal_case(self->content, other);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/*
+ * trio_string_equal_case_max
+ */
+TRIO_STRING_PUBLIC int
+trio_string_equal_case_max
+TRIO_ARGS3((self, max, other),
+ trio_string_t *self,
+ size_t max,
+ trio_string_t *other)
+{
+ assert(self);
+ assert(other);
+
+ return trio_equal_case_max(self->content, max, other->content);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/*
+ * trio_xstring_equal_case_max
+ */
+TRIO_STRING_PUBLIC int
+trio_xstring_equal_case_max
+TRIO_ARGS3((self, max, other),
+ trio_string_t *self,
+ size_t max,
+ TRIO_CONST char *other)
+{
+ assert(self);
+ assert(other);
+
+ return trio_equal_case_max(self->content, max, other);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/*
+ * trio_string_format_data_max
+ */
+TRIO_STRING_PUBLIC size_t
+trio_string_format_date_max
+TRIO_ARGS4((self, max, format, datetime),
+ trio_string_t *self,
+ size_t max,
+ TRIO_CONST char *format,
+ TRIO_CONST struct tm *datetime)
+{
+ assert(self);
+
+ return trio_format_date_max(self->content, max, format, datetime);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/*
+ * trio_string_index
+ */
+TRIO_STRING_PUBLIC char *
+trio_string_index
+TRIO_ARGS2((self, character),
+ trio_string_t *self,
+ int character)
+{
+ assert(self);
+
+ return trio_index(self->content, character);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/*
+ * trio_string_index_last
+ */
+TRIO_STRING_PUBLIC char *
+trio_string_index_last
+TRIO_ARGS2((self, character),
+ trio_string_t *self,
+ int character)
+{
+ assert(self);
+
+ return trio_index_last(self->content, character);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/*
+ * trio_string_length
+ */
+TRIO_STRING_PUBLIC int
+trio_string_length
+TRIO_ARGS1((self),
+ trio_string_t *self)
+{
+ assert(self);
+
+ if (self->length == 0)
+ {
+ self->length = trio_length(self->content);
+ }
+ return self->length;
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/*
+ * trio_string_lower
+ */
+TRIO_STRING_PUBLIC int
+trio_string_lower
+TRIO_ARGS1((self),
+ trio_string_t *self)
+{
+ assert(self);
+
+ return trio_lower(self->content);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/*
+ * trio_string_match
+ */
+TRIO_STRING_PUBLIC int
+trio_string_match
+TRIO_ARGS2((self, other),
+ trio_string_t *self,
+ trio_string_t *other)
+{
+ assert(self);
+ assert(other);
+
+ return trio_match(self->content, other->content);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/*
+ * trio_xstring_match
+ */
+TRIO_STRING_PUBLIC int
+trio_xstring_match
+TRIO_ARGS2((self, other),
+ trio_string_t *self,
+ TRIO_CONST char *other)
+{
+ assert(self);
+ assert(other);
+
+ return trio_match(self->content, other);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/*
+ * trio_string_match_case
+ */
+TRIO_STRING_PUBLIC int
+trio_string_match_case
+TRIO_ARGS2((self, other),
+ trio_string_t *self,
+ trio_string_t *other)
+{
+ assert(self);
+ assert(other);
+
+ return trio_match_case(self->content, other->content);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/*
+ * trio_xstring_match_case
+ */
+TRIO_STRING_PUBLIC int
+trio_xstring_match_case
+TRIO_ARGS2((self, other),
+ trio_string_t *self,
+ TRIO_CONST char *other)
+{
+ assert(self);
+ assert(other);
+
+ return trio_match_case(self->content, other);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/*
+ * trio_string_substring
+ */
+TRIO_STRING_PUBLIC char *
+trio_string_substring
+TRIO_ARGS2((self, other),
+ trio_string_t *self,
+ trio_string_t *other)
+{
+ assert(self);
+ assert(other);
+
+ return trio_substring(self->content, other->content);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/*
+ * trio_xstring_substring
+ */
+TRIO_STRING_PUBLIC char *
+trio_xstring_substring
+TRIO_ARGS2((self, other),
+ trio_string_t *self,
+ TRIO_CONST char *other)
+{
+ assert(self);
+ assert(other);
+
+ return trio_substring(self->content, other);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+
+#if !defined(TRIO_MINIMAL)
+/*
+ * trio_string_upper
+ */
+TRIO_STRING_PUBLIC int
+trio_string_upper
+TRIO_ARGS1((self),
+ trio_string_t *self)
+{
+ assert(self);
+
+ return trio_upper(self->content);
+}
+#endif /* !defined(TRIO_MINIMAL) */
+
+/** @} End of DynamicStrings */
diff --git a/trio/triostr.h b/trio/triostr.h
new file mode 100644
index 00000000..edec4264
--- /dev/null
+++ b/trio/triostr.h
@@ -0,0 +1,140 @@
+/*************************************************************************
+ *
+ * $Id: triostr.h,v 1.10 2003/03/01 15:34:01 breese Exp $
+ *
+ * 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_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 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_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_length TRIO_PROTO((const char *string));
+TRIO_STRING_PUBLIC double trio_to_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 trio_long_double_t trio_to_long_double TRIO_PROTO((const char *source, char **endp));
+TRIO_STRING_PUBLIC int trio_to_upper TRIO_PROTO((int source));
+
+#if !defined(TRIO_MINIMAL)
+
+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 char *trio_duplicate_max TRIO_PROTO((const char *source, size_t max));
+TRIO_STRING_PUBLIC int trio_equal_case_max TRIO_PROTO((const char *first, size_t max, const char *second));
+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 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 float trio_to_float TRIO_PROTO((const char *source, char **endp));
+TRIO_STRING_PUBLIC int trio_to_lower TRIO_PROTO((int source));
+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));
+
+#endif /* !defined(TRIO_MINIMAL) */
+
+/*************************************************************************
+ * Dynamic string functions
+ */
+
+/*
+ * Opaque type for dynamic strings
+ */
+
+typedef struct _trio_string_t trio_string_t;
+
+TRIO_STRING_PUBLIC void trio_string_destroy TRIO_PROTO((trio_string_t *self));
+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_xstring_append_char TRIO_PROTO((trio_string_t *self, char character));
+TRIO_STRING_PUBLIC trio_string_t *trio_xstring_duplicate TRIO_PROTO((const char *other));
+
+#if !defined(TRIO_MINIMAL)
+
+TRIO_STRING_PUBLIC trio_string_t *trio_string_create TRIO_PROTO((int initial_size));
+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 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 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 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 /* !defined(TRIO_MINIMAL) */
+
+#endif /* TRIO_TRIOSTR_H */