applied a trio update patch from Bjorn Reese which should work with MinGW

* trio.c trio.h triodef.h trionan.c trionan.h triop.h
  triostr.c triostr.h: applied a trio update patch from
  Bjorn Reese which should work with MinGW
Daniel
diff --git a/ChangeLog b/ChangeLog
index 24f596a..fe4ae65 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Thu Sep 26 00:31:46 CEST 2002 Daniel Veillard <daniel@veillard.com>
+
+	* trio.c trio.h triodef.h trionan.c trionan.h triop.h
+	  triostr.c triostr.h: applied a trio update patch from 
+	  Bjorn Reese which should work with MinGW
+
 Thu Sep 26 00:21:18 CEST 2002 Daniel Veillard <daniel@veillard.com>
 
 	* tree.c: improving some documentation comments
diff --git a/doc/FAQ.html b/doc/FAQ.html
index 34e39f5..508ddf6 100644
--- a/doc/FAQ.html
+++ b/doc/FAQ.html
@@ -119,7 +119,7 @@
     Not Use libxml1</span></strong>, use libxml2</li>
   <li>
 <em>Where can I get libxml</em> ?
-    <p>The original distribution comes from <a href="ftp://rpmfind.net/pub/libxml/">rpmfind.net</a> or <a href="ftp://ftp.gnome.org/pub/GNOME/stable/sources/libxml/">gnome.org</a>
+    <p>The original distribution comes from <a href="ftp://rpmfind.net/pub/libxml/">rpmfind.net</a> or <a href="ftp://ftp.gnome.org/pub/GNOME/sources/libxml2/2.4/">gnome.org</a>
 </p>
     <p>Most Linux and BSD distributions include libxml, this is probably the
     safer way for end-users to use libxml.</p>
diff --git a/doc/downloads.html b/doc/downloads.html
index 7ee3639..b04e9e9 100644
--- a/doc/downloads.html
+++ b/doc/downloads.html
@@ -89,9 +89,8 @@
 </td></tr></table></td>
 <td valign="top" bgcolor="#8b7765"><table border="0" cellspacing="0" cellpadding="1" width="100%"><tr><td><table border="0" cellspacing="0" cellpadding="1" width="100%" bgcolor="#000000"><tr><td><table border="0" cellpadding="3" cellspacing="1" width="100%"><tr><td bgcolor="#fffacd">
 <p>The latest versions of libxml can be found on <a href="ftp://xmlsoft.org/">xmlsoft.org</a> (<a href="ftp://speakeasy.rpmfind.net/pub/libxml/">Seattle</a>, <a href="ftp://fr.rpmfind.net/pub/libxml/">France</a>) or on the <a href="ftp://ftp.gnome.org/pub/GNOME/MIRRORS.html">Gnome FTP server</a> either
-as a <a href="ftp://ftp.gnome.org/pub/GNOME/stable/sources/libxml/">source
-archive</a> or <a href="ftp://ftp.gnome.org/pub/GNOME/stable/redhat/i386/libxml/">RPM
-packages</a>, Antonin Sprinzl also provide <a href="ftp://gd.tuwien.ac.at/pub/libxml/">a mirror in Austria</a>. (NOTE that
+as a <a href="ftp://ftp.gnome.org/pub/GNOME/sources/libxml2/2.4/">source
+archive</a>, Antonin Sprinzl also provide <a href="ftp://gd.tuwien.ac.at/pub/libxml/">a mirror in Austria</a>. (NOTE that
 you need both the <a href="http://rpmfind.net/linux/RPM/libxml2.html">libxml(2)</a> and <a href="http://rpmfind.net/linux/RPM/libxml2-devel.html">libxml(2)-devel</a>
 packages installed to compile applications using libxml.) <a href="mailto:igor@stud.fh-frankfurt.de">Igor  Zlatkovic</a> is now the
 maintainer of the Windows port, <a href="http://www.fh-frankfurt.de/~igor/projects/libxml/index.html">he
diff --git a/trio.c b/trio.c
index 1a844bc..7593e58 100644
--- a/trio.c
+++ b/trio.c
@@ -28,7 +28,6 @@
  * TODO:
  *  - Scan is probably too permissive about its modifiers.
  *  - C escapes in %#[] ?
- *  - C99 support has not been properly tested.
  *  - Multibyte characters (done for format parsing, except scan groups)
  *  - Complex numbers? (C99 _Complex)
  *  - Boolean values? (C99 _Bool)
@@ -47,19 +46,17 @@
 #include "triodef.h"
 #include "trio.h"
 #include "triop.h"
-#include "triostr.h"
 #include "trionan.h"
-
-/*
- * Encode the error code and the position. This is decoded
- * with TRIO_ERROR_CODE and TRIO_ERROR_POSITION.
- */
-#if TRIO_ERRORS
-# define TRIO_ERROR_RETURN(x,y) (- ((x) + ((y) << 8)))
-#else
-# define TRIO_ERROR_RETURN(x,y) (-1)
+#if !defined(TRIO_MINIMAL)
+# include "triostr.h"
 #endif
 
+/**************************************************************************
+ *
+ * Definitions
+ *
+ *************************************************************************/
+
 #if defined(__STDC_ISO_10646__) || defined(MB_LEN_MAX) || defined(USE_MULTIBYTE) || TRIO_WIDECHAR
 # define TRIO_COMPILER_SUPPORTS_MULTIBYTE
 # if !defined(MB_LEN_MAX)
@@ -67,7 +64,6 @@
 # endif
 #endif
 
-
 /*************************************************************************
  * Generic definitions
  */
@@ -83,7 +79,11 @@
 #include <math.h>
 #include <limits.h>
 #include <float.h>
-#include <stdarg.h>
+#if defined(TRIO_COMPILER_ANCIENT)
+# include <varargs.h>
+#else
+# include <stdarg.h>
+#endif
 #include <stddef.h>
 #include <errno.h>
 
@@ -100,9 +100,15 @@
 /* mincore() can be used for debugging purposes */
 #define VALID(x) (NULL != (x))
 
-/* xlC crashes on log10(0) */
-#define guarded_log10(x) (((x) == 0.0) ? trio_ninf() : log10(x))
-#define guarded_log16(x) (guarded_log10(x) / log10(16.0))
+#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
 
 
 /*************************************************************************
@@ -129,9 +135,11 @@
 # 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 wchar_t;
-typedef int wint_t;
+typedef char trio_wchar_t;
+typedef int trio_wint_t;
 #  define WCONST(x) L ## x
 #  define WEOF EOF
 #  define iswalnum(x) isalnum(x)
@@ -180,7 +188,7 @@
 typedef unsigned long int trio_ulonglong_t;
 # endif
 #else
-typedef signed long int trio_longlong_t;
+typedef TRIO_SIGNED long int trio_longlong_t;
 typedef unsigned long int trio_ulonglong_t;
 #endif
 
@@ -214,17 +222,17 @@
 # if defined(TRIO_INT8_T)
 typedef TRIO_INT8_T trio_int8_t;
 # else
-typedef signed char trio_int8_t;
+typedef TRIO_SIGNED char trio_int8_t;
 # endif
 # if defined(TRIO_INT16_T)
 typedef TRIO_INT16_T trio_int16_t;
 # else
-typedef signed short trio_int16_t;
+typedef TRIO_SIGNED short trio_int16_t;
 # endif
 # if defined(TRIO_INT32_T)
 typedef TRIO_INT32_T trio_int32_t;
 # else
-typedef signed int trio_int32_t;
+typedef TRIO_SIGNED int trio_int32_t;
 # endif
 # if defined(TRIO_INT64_T)
 typedef TRIO_INT64_T trio_int64_t;
@@ -233,24 +241,47 @@
 # 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
+ * 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 DBL_DIG
+# 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(void *) * CHAR_BIT / 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"
@@ -301,6 +332,7 @@
   /* 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,
@@ -310,6 +342,7 @@
   NO_PRECISION = -1,
   NO_SIZE      = -1,
 
+  /* Do not change these */
   NO_BASE      = -1,
   MIN_BASE     =  2,
   MAX_BASE     = 36,
@@ -362,18 +395,18 @@
 #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:"
+#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:
@@ -543,7 +576,7 @@
 #define QUALIFIER_MINUS '-'
 #define QUALIFIER_DOT '.'
 #define QUALIFIER_STAR '*'
-#define QUALIFIER_CIRCUMFLEX '^'
+#define QUALIFIER_CIRCUMFLEX '^' /* For scanlists */
 #if TRIO_C99
 # define QUALIFIER_SIZE_T 'z'
 # define QUALIFIER_PTRDIFF_T 't'
@@ -568,12 +601,15 @@
 # define QUALIFIER_PARAM '@' /* Experimental */
 # define QUALIFIER_COLON ':' /* For scanlists */
 # define QUALIFIER_EQUAL '=' /* For scanlists */
+# define QUALIFIER_ROUNDING_UPPER 'R'
 #endif
 
 
 /*************************************************************************
- * Internal structures
- */
+ *
+ * Internal Structures
+ *
+ *************************************************************************/
 
 /* Parameters */
 typedef struct {
@@ -595,17 +631,17 @@
   union {
     char *string;
 #if TRIO_WIDECHAR
-    wchar_t *wstring;
+    trio_wchar_t *wstring;
 #endif
-    void *pointer;
+    trio_pointer_t pointer;
     union {
-      trio_uintmax_t as_signed;
-      trio_intmax_t as_unsigned;
+      trio_intmax_t as_signed;
+      trio_uintmax_t as_unsigned;
     } number;
     double doubleNumber;
     double *doublePointer;
-    long double longdoubleNumber;
-    long double *longdoublePointer;
+    trio_long_double_t longdoubleNumber;
+    trio_long_double_t *longdoublePointer;
     int errorNumber;
   } data;
   /* For the user-defined specifier */
@@ -613,20 +649,29 @@
   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)(struct _trio_class_t *, int);
+  void (*OutStream) TRIO_PROTO((struct _trio_class_t *, int));
   /*
    * The function to read characters from a stream.
    */
-  void (*InStream)(struct _trio_class_t *, int *);
+  void (*InStream) TRIO_PROTO((struct _trio_class_t *, int *));
   /*
    * The current location in the stream.
    */
-  void *location;
+  trio_pointer_t location;
   /*
    * The character currently being processed.
    */
@@ -667,8 +712,10 @@
 
 
 /*************************************************************************
- * Internal variables
- */
+ *
+ * Internal Variables
+ *
+ *************************************************************************/
 
 static TRIO_CONST char rcsid[] = "@(#)$Id$";
 
@@ -678,7 +725,7 @@
  * e.g: va_arg(arg_ptr, long double)
  */
 #if defined(TRIO_PLATFORM_MPEIX)
-static TRIO_CONST long double ___dummy_long_double = 0;
+static TRIO_CONST trio_long_double_t ___dummy_long_double = 0;
 #endif
 
 static TRIO_CONST char internalNullString[] = "(nil)";
@@ -691,7 +738,10 @@
  * UNIX98 says "in a locale where the radix character is not defined,
  * the radix character defaults to a period (.)"
  */
-static char internalDecimalPoint[MAX_LOCALE_SEPARATOR_LENGTH + 1] = ".";
+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 };
 
@@ -704,38 +754,23 @@
 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
 
 
 /*************************************************************************
- * trio_strerror
- */
-TRIO_PUBLIC TRIO_CONST char *
-trio_strerror(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";
-    default:
-      return "Unknown";
-    }
-}
+ *
+ * Internal Functions
+ *
+ ************************************************************************/
+
+#if defined(TRIO_MINIMAL)
+# define TRIO_STRING_PUBLIC static
+# include "triostr.c"
+#endif /* defined(TRIO_MINIMAL) */
 
 /*************************************************************************
  * TrioIsQualifier
@@ -745,10 +780,12 @@
  *  QUALIFIER_POSITION must not be added.
  */
 TRIO_PRIVATE BOOLEAN_T
-TrioIsQualifier(TRIO_CONST char ch)
+TrioIsQualifier
+TRIO_ARGS1((character),
+	   TRIO_CONST char character)
 {
   /* QUALIFIER_POSITION is not included */
-  switch (ch)
+  switch (character)
     {
     case '0': case '1': case '2': case '3': case '4':
     case '5': case '6': case '7': case '8': case '9':
@@ -795,6 +832,9 @@
 #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;
@@ -805,8 +845,8 @@
  * TrioSetLocale
  */
 #if defined(USE_LOCALE)
-TRIO_PUBLIC void
-TrioSetLocale(void)
+TRIO_PRIVATE void
+TrioSetLocale(TRIO_NOARGS)
 {
   internalLocaleValues = (struct lconv *)localeconv();
   if (internalLocaleValues)
@@ -814,9 +854,18 @@
       if ((internalLocaleValues->decimal_point) &&
 	  (internalLocaleValues->decimal_point[0] != NIL))
 	{
-	  trio_copy_max(internalDecimalPoint,
-			sizeof(internalDecimalPoint),
-			internalLocaleValues->decimal_point);
+	  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))
@@ -824,6 +873,7 @@
 	  trio_copy_max(internalThousandSeparator,
 			sizeof(internalThousandSeparator),
 			internalLocaleValues->thousands_sep);
+	  internalThousandSeparatorLength = trio_length(internalThousandSeparator);
 	}
       if ((internalLocaleValues->grouping) &&
 	  (internalLocaleValues->grouping[0] != NIL))
@@ -836,15 +886,91 @@
 }
 #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_CONST char *format,
-		int *indexPointer)
+TrioGetPosition
+TRIO_ARGS2((format, indexPointer),
+	   TRIO_CONST char *format,
+	   int *indexPointer)
 {
+#if TRIO_UNIX98
   char *tmpformat;
   int number = 0;
   int index = *indexPointer;
@@ -860,17 +986,22 @@
        */
       return number - 1;
     }
+#endif
   return NO_POSITION;
 }
 
+#if TRIO_EXTENSION
 /*************************************************************************
  * TrioFindNamespace
  *
  * Find registered user-defined specifier.
- * The prev argument is used for optimisation only.
+ * The prev argument is used for optimization only.
  */
 TRIO_PRIVATE trio_userdef_t *
-TrioFindNamespace(TRIO_CONST char *name, trio_userdef_t **prev)
+TrioFindNamespace
+TRIO_ARGS2((name, prev),
+	   TRIO_CONST char *name,
+	   trio_userdef_t **prev)
 {
   trio_userdef_t *def;
   
@@ -892,6 +1023,117 @@
   
   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
@@ -900,16 +1142,16 @@
  *  Parse the format string
  */
 TRIO_PRIVATE int
-TrioParse(int type,
-	  TRIO_CONST char *format,
-	  trio_parameter_t *parameters,
-	  va_list arglist,
-	  void **argarray)
+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)
 {
-#if TRIO_ERRORS
   /* Count the number of times a parameter is referenced */
   unsigned short usedEntries[MAX_PARAMETERS];
-#endif
   /* Parameter counters */
   int parameterPosition;
   int currentParam;
@@ -923,7 +1165,7 @@
   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 got_sticky = FALSE;  /* Are there any sticky modifiers at all? */
+  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)
@@ -935,23 +1177,25 @@
 #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
   int charlen;
 #endif
+  int save_errno;
   int i = -1;
   int num;
   char *tmpformat;
 
-
-#if TRIO_ERRORS
+  /* 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));
-#endif
 
+  save_errno = errno;
   index = 0;
   parameterPosition = 0;
 #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
-  mblen(NULL, 0);
+  (void)mblen(NULL, 0);
 #endif
   
   while (format[index])
@@ -1034,8 +1278,11 @@
 		      
 		      /* After the first dot we have the precision */
 		      flags |= FLAGS_PRECISION;
-		      if ((QUALIFIER_STAR == format[index]) ||
-			  (QUALIFIER_PARAM == format[index]))
+		      if ((QUALIFIER_STAR == format[index])
+#if defined(QUALIFIER_PARAM)
+			  || (QUALIFIER_PARAM == format[index])
+#endif
+			  )
 			{
 			  index++;
 			  flags |= FLAGS_PRECISION_PARAMETER;
@@ -1076,8 +1323,11 @@
 		      
 		      /* After the second dot we have the base */
 		      flags |= FLAGS_BASE;
-		      if ((QUALIFIER_STAR == format[index]) ||
-			  (QUALIFIER_PARAM == format[index]))
+		      if ((QUALIFIER_STAR == format[index])
+#if defined(QUALIFIER_PARAM)
+			  || (QUALIFIER_PARAM == format[index])
+#endif
+			  )
 			{
 			  index++;
 			  flags |= FLAGS_BASE_PARAMETER;
@@ -1119,9 +1369,11 @@
 		    }
 		  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)
@@ -1292,7 +1544,7 @@
 #if defined(QUALIFIER_STICKY)
 		case QUALIFIER_STICKY:
 		  flags |= FLAGS_STICKY;
-		  got_sticky = TRUE;
+		  gotSticky = TRUE;
 		  break;
 #endif
 		  
@@ -1312,6 +1564,12 @@
 		  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);
@@ -1324,9 +1582,7 @@
 	   */
 	  if (flags & FLAGS_WIDTH_PARAMETER)
 	    {
-#if TRIO_ERRORS
 	      usedEntries[width] += 1;
-#endif
 	      parameters[pos].type = FORMAT_PARAMETER;
 	      parameters[pos].flags = 0;
 	      indices[width] = pos;
@@ -1334,9 +1590,7 @@
 	    }
 	  if (flags & FLAGS_PRECISION_PARAMETER)
 	    {
-#if TRIO_ERRORS
 	      usedEntries[precision] += 1;
-#endif
 	      parameters[pos].type = FORMAT_PARAMETER;
 	      parameters[pos].flags = 0;
 	      indices[precision] = pos;
@@ -1344,9 +1598,7 @@
 	    }
 	  if (flags & FLAGS_BASE_PARAMETER)
 	    {
-#if TRIO_ERRORS
 	      usedEntries[base] += 1;
-#endif
 	      parameters[pos].type = FORMAT_PARAMETER;
 	      parameters[pos].flags = 0;
 	      indices[base] = pos;
@@ -1354,9 +1606,7 @@
 	    }
 	  if (flags & FLAGS_VARSIZE_PARAMETER)
 	    {
-#if TRIO_ERRORS
 	      usedEntries[varsize] += 1;
-#endif
 	      parameters[pos].type = FORMAT_PARAMETER;
 	      parameters[pos].flags = 0;
 	      indices[varsize] = pos;
@@ -1492,6 +1742,10 @@
 	      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;
 
@@ -1540,9 +1794,7 @@
 			    parameters[pos].flags = FLAGS_USER_DEFINED;
 			    /* Adjust parameters for insertion of new one */
 			    pos++;
-# if TRIO_ERRORS
 			    usedEntries[currentParam] += 1;
-# endif
 			    parameters[pos].type = FORMAT_USER_DEFINED;
 			    currentParam++;
 			    indices[currentParam] = pos;
@@ -1582,13 +1834,11 @@
               return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
 	    }
 
-#if TRIO_ERRORS
 	  /*  Count the number of times this entry has been used */
 	  usedEntries[currentParam] += 1;
-#endif
 	  
 	  /* Find last sticky parameters */
-	  if (got_sticky && !(flags & FLAGS_STICKY))
+	  if (gotSticky && !(flags & FLAGS_STICKY))
 	    {
 	      for (i = pos - 1; i >= 0; i--)
 		{
@@ -1627,7 +1877,6 @@
 
   for (num = 0; num <= maxParam; num++)
     {
-#if TRIO_ERRORS
       if (usedEntries[num] != 1)
 	{
 	  if (usedEntries[num] == 0) /* gap detected */
@@ -1635,7 +1884,6 @@
 	  else /* double references detected */
 	    return TRIO_ERROR_RETURN(TRIO_EDBLREF, num);
 	}
-#endif
       
       i = indices[num];
 
@@ -1676,24 +1924,26 @@
 	  if (flags & FLAGS_WIDECHAR)
 	    {
 	      parameters[i].data.wstring = (argarray == NULL)
-		? va_arg(arglist, wchar_t *)
-		: (wchar_t *)(argarray[num]);
+		? va_arg(*arglist, trio_wchar_t *)
+		: (trio_wchar_t *)(argarray[num]);
 	    }
 	  else
 #endif
 	    {
 	      parameters[i].data.string = (argarray == NULL)
-		? va_arg(arglist, char *)
+		? 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_USER_DEFINED:
 	case FORMAT_UNKNOWN:
 	  parameters[i].data.pointer = (argarray == NULL)
-	    ? va_arg(arglist, void *)
+	    ? va_arg(*arglist, trio_pointer_t )
 	    : argarray[num];
 	  break;
 
@@ -1703,18 +1953,18 @@
 	    {
               if (argarray == NULL)
                 parameters[i].data.pointer = 
-                  (trio_uintmax_t *)va_arg(arglist, void *);
+                  (trio_pointer_t)va_arg(*arglist, trio_pointer_t);
               else
                 {
                   if (parameters[i].type == FORMAT_CHAR)
                     parameters[i].data.pointer =
-                      (trio_uintmax_t *)((char *)argarray[num]);
+                      (trio_pointer_t)((char *)argarray[num]);
                   else if (parameters[i].flags & FLAGS_SHORT)
                     parameters[i].data.pointer =
-                      (trio_uintmax_t *)((short *)argarray[num]);
+                      (trio_pointer_t)((short *)argarray[num]);
                   else
                     parameters[i].data.pointer =
-                      (trio_uintmax_t *)((int *)argarray[num]);
+                      (trio_pointer_t)((int *)argarray[num]);
                 }
 	    }
 	  else
@@ -1761,36 +2011,36 @@
 #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)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)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)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)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)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);
+		    parameters[i].data.number.as_unsigned = (trio_uintmax_t)va_arg(*arglist, int);
 		  else
 		    {
 		      if (parameters[i].type == FORMAT_CHAR)
@@ -1811,56 +2061,52 @@
 	   */
 	  if (parameters[i].flags & FLAGS_USER_DEFINED)
 	    parameters[i].data.pointer = (argarray == NULL)
-	      ? va_arg(arglist, void *)
+	      ? 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)va_arg(*arglist, int)
 	      : (trio_uintmax_t)(*((int *)argarray[num]));
 	  break;
 
 	case FORMAT_DOUBLE:
 	  if (TYPE_SCAN == type)
 	    {
-	      if (parameters[i].flags & FLAGS_LONG)
+	      if (parameters[i].flags & FLAGS_LONGDOUBLE)
 		parameters[i].data.longdoublePointer = (argarray == NULL)
-		  ? va_arg(arglist, long double *)
-		  : (long double *)((long double *)argarray[num]);
+		  ? va_arg(*arglist, trio_long_double_t *)
+		  : (trio_long_double_t *)argarray[num];
 	      else
                 {
-                  if (argarray == NULL)
-                    parameters[i].data.doublePointer =
-                      va_arg(arglist, double *);
-                 else
-                   {
-                     if (parameters[i].flags & FLAGS_SHORT)
-                       parameters[i].data.doublePointer =
-                         (double *)((float *)argarray[num]);
-                     else
-                       parameters[i].data.doublePointer =
-                         (double *)((double *)argarray[num]);
-                   }
+		  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_LONG)
+	      if (parameters[i].flags & FLAGS_LONGDOUBLE)
 		parameters[i].data.longdoubleNumber = (argarray == NULL)
-		  ? va_arg(arglist, long double)
-		  : (long double)(*((long double *)argarray[num]));
+		  ? 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 =
-		      (long double)va_arg(arglist, double);
+		      (trio_long_double_t)va_arg(*arglist, double);
 		  else
 		    {
 		      if (parameters[i].flags & FLAGS_SHORT)
 			parameters[i].data.longdoubleNumber =
-			  (long double)(*((float *)argarray[num]));
+			  (trio_long_double_t)(*((float *)argarray[num]));
 		      else
 			parameters[i].data.longdoubleNumber =
-			  (long double)(long double)(*((double *)argarray[num]));
+			  (trio_long_double_t)(*((double *)argarray[num]));
 		    }
 		}
 	    }
@@ -1868,7 +2114,7 @@
 
 #if defined(FORMAT_ERRNO)
 	case FORMAT_ERRNO:
-	  parameters[i].data.errorNumber = errno;
+	  parameters[i].data.errorNumber = save_errno;
 	  break;
 #endif
 
@@ -1896,12 +2142,14 @@
  *  of the dependencies of the flags.
  */
 TRIO_PRIVATE void
-TrioWriteNumber(trio_class_t *self,
-		trio_uintmax_t number,
-		unsigned long flags,
-		int width,
-		int precision,
-		int base)
+TrioWriteNumber
+TRIO_ARGS6((self, number, flags, width, precision, base),
+	   trio_class_t *self,
+	   trio_uintmax_t number,
+	   unsigned long flags,
+	   int width,
+	   int precision,
+	   int base)
 {
   BOOLEAN_T isNegative;
   char buffer[MAX_CHARS_IN(trio_uintmax_t) * (1 + MAX_LOCALE_SEPARATOR_LENGTH) + 1];
@@ -1911,8 +2159,6 @@
   int i;
   int length;
   char *p;
-  int charsPerThousand;
-  int groupingIndex;
   int count;
 
   assert(VALID(self));
@@ -1920,12 +2166,14 @@
   assert(((base >= MIN_BASE) && (base <= MAX_BASE)) || (base == NO_BASE));
 
   digits = (flags & FLAGS_UPPER) ? internalDigitsUpper : internalDigitsLower;
+  if (base == NO_BASE)
+    base = BASE_DECIMAL;
 
   isNegative = (flags & FLAGS_UNSIGNED)
     ? FALSE
     : ((trio_intmax_t)number < 0);
   if (isNegative)
-    number = -number;
+    number = -((trio_intmax_t)number);
 
   if (flags & FLAGS_QUAD)
     number &= (trio_ulonglong_t)-1;
@@ -1937,8 +2185,6 @@
   /* Build number */
   pointer = bufferend = &buffer[sizeof(buffer) - 1];
   *pointer-- = NIL;
-  charsPerThousand = (int)internalGrouping[0];
-  groupingIndex = 1;
   for (i = 1; i < (int)sizeof(buffer); i++)
     {
       *pointer-- = digits[number % base];
@@ -1946,35 +2192,20 @@
       if (number == 0)
 	break;
 
-      if ((flags & FLAGS_QUOTE)
-	  && (charsPerThousand != NO_GROUPING)
-	  && (i % charsPerThousand == 0))
+      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 = trio_length(internalThousandSeparator);
+	  length = internalThousandSeparatorLength;
 	  if (((int)(pointer - buffer) - length) > 0)
 	    {
 	      p = &internalThousandSeparator[length - 1];
 	      while (length-- > 0)
 		*pointer-- = *p--;
 	    }
-
-	  /* Advance to next grouping number */
-	  switch (internalGrouping[groupingIndex])
-	    {
-	    case CHAR_MAX: /* Disable grouping */
-	      charsPerThousand = NO_GROUPING;
-	      break;
-	    case 0: /* Repeat last group */
-	      break;
-	    default:
-	      charsPerThousand = (int)internalGrouping[groupingIndex++];
-	      break;
-	    }
 	}
     }
 
@@ -2082,13 +2313,15 @@
  *  Output a single character of a string
  */
 TRIO_PRIVATE void
-TrioWriteStringCharacter(trio_class_t *self,
-			 int ch,
-			 unsigned long flags)
+TrioWriteStringCharacter
+TRIO_ARGS3((self, ch, flags),
+	   trio_class_t *self,
+	   int ch,
+	   unsigned long flags)
 {
   if (flags & FLAGS_ALTERNATIVE)
     {
-      if (! (isprint(ch) || isspace(ch)))
+      if (! isprint(ch))
 	{
 	  /*
 	   * Non-printable characters are converted to C escapes or
@@ -2107,7 +2340,7 @@
 	    case '\\': self->OutStream(self, '\\'); break;
 	    default:
 	      self->OutStream(self, 'x');
-	      TrioWriteNumber(self, (trio_intmax_t)ch,
+	      TrioWriteNumber(self, (trio_uintmax_t)ch,
 			      FLAGS_UNSIGNED | FLAGS_NILPADDING,
 			      2, 2, BASE_HEX);
 	      break;
@@ -2136,11 +2369,13 @@
  *  Output a string
  */
 TRIO_PRIVATE void
-TrioWriteString(trio_class_t *self,
-		TRIO_CONST char *string,
-		unsigned long flags,
-		int width,
-		int precision)
+TrioWriteString
+TRIO_ARGS5((self, string, flags, width, precision),
+	   trio_class_t *self,
+	   TRIO_CONST char *string,
+	   unsigned long flags,
+	   int width,
+	   int precision)
 {
   int length;
   int ch;
@@ -2200,10 +2435,12 @@
  */
 #if TRIO_WIDECHAR
 TRIO_PRIVATE int
-TrioWriteWideStringCharacter(trio_class_t *self,
-			     wchar_t wch,
-			     unsigned long flags,
-			     int width)
+TrioWriteWideStringCharacter
+TRIO_ARGS4((self, wch, flags, width),
+	   trio_class_t *self,
+	   trio_wchar_t wch,
+	   unsigned long flags,
+	   int width)
 {
   int size;
   int i;
@@ -2238,11 +2475,13 @@
  */
 #if TRIO_WIDECHAR
 TRIO_PRIVATE void
-TrioWriteWideString(trio_class_t *self,
-		    TRIO_CONST wchar_t *wstring,
-		    unsigned long flags,
-		    int width,
-		    int precision)
+TrioWriteWideString
+TRIO_ARGS5((self, wstring, flags, width, precision),
+	   trio_class_t *self,
+	   TRIO_CONST trio_wchar_t *wstring,
+	   unsigned long flags,
+	   int width,
+	   int precision)
 {
   int length;
   int size;
@@ -2251,7 +2490,7 @@
   assert(VALID(self->OutStream));
 
 #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
-  mblen(NULL, 0);
+  (void)mblen(NULL, 0);
 #endif
   
   if (wstring == NULL)
@@ -2299,100 +2538,155 @@
 
 /*************************************************************************
  * 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_class_t *self,
-		long double longdoubleNumber,
-		unsigned long flags,
-		int width,
-		int precision,
-		int base)
+TrioWriteDouble
+TRIO_ARGS6((self, number, flags, width, precision, base),
+	   trio_class_t *self,
+	   trio_long_double_t number,
+	   unsigned long flags,
+	   int width,
+	   int precision,
+	   int base)
 {
-  int charsPerThousand;
-  int length;
-  double number;
-  double workNumber;
+  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;
+  int exponent = 0;
   unsigned int uExponent = 0;
-  double dblBase;
+  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 numberBuffer[MAX_MANTISSA_DIGITS
-		   * (1 + MAX_LOCALE_SEPARATOR_LENGTH) + 1];
-  char *numberPointer;
-  char exponentBuffer[MAX_EXPONENT_DIGITS + 1];
-  char *exponentPointer = NULL;
-  int groupingIndex;
-  char *work;
+  char *groupingPointer;
   int i;
-  BOOLEAN_T onlyzero;
+  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 == BASE_DECIMAL || base == BASE_HEX);
+  assert(((base >= MIN_BASE) && (base <= MAX_BASE)) || (base == NO_BASE));
 
-  number = (double)longdoubleNumber;
-  
-  /* Look for infinite numbers and non-a-number first */
-  switch (trio_isinf(number))
+  /* Determine sign and look for special quantities */
+  switch (trio_fpclassify_and_signbit(number, &isNegative))
     {
-    case 1:
-      /* Positive infinity */
-      TrioWriteString(self,
-		      (flags & FLAGS_UPPER)
-		      ? INFINITE_UPPER
-		      : INFINITE_LOWER,
-		      flags, width, precision);
-      return;
-
-    case -1:
-      /* Negative infinity */
-      TrioWriteString(self,
-		      (flags & FLAGS_UPPER)
-		      ? "-" INFINITE_UPPER
-		      : "-" INFINITE_LOWER,
-		      flags, width, precision);
-      return;
-
-    default:
-      /* Finitude */
-      break;
-    }
-  if (trio_isnan(number))
-    {
+    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;
     }
 
-  /* Normal numbers */
   digits = (flags & FLAGS_UPPER) ? internalDigitsUpper : internalDigitsLower;
   isHex = (base == BASE_HEX);
-  dblBase = (double)base;
+  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)
     precision = FLT_DIG;
   
-  isNegative = (number < 0.0);
   if (isNegative)
     number = -number;
 
-  if ((flags & FLAGS_FLOAT_G) || isHex)
+  if (isHex)
+    flags |= FLAGS_FLOAT_E;
+  
+  if (flags & FLAGS_FLOAT_G)
     {
       if (precision == 0)
 	precision = 1;
 
-      if ((number < 1.0e-4) || (number > pow(10.0, (double)precision)))
+      if ((number < 1.0E-4) || (number > powl(base,
+					      (trio_long_double_t)precision)))
 	{
 	  /* Use scientific notation */
 	  flags |= FLAGS_FLOAT_E;
@@ -2404,17 +2698,18 @@
 	   * zero, then adjust the precision to include leading fractional
 	   * zeros.
 	   */
-	  workNumber = fabs(guarded_log10(number));
-	  if (workNumber - floor(workNumber) < 0.001)
+	  workNumber = TrioLogarithm(number, base);
+	  workNumber = TRIO_FABS(workNumber);
+	  if (workNumber - floorl(workNumber) < 0.001)
 	    workNumber--;
-	  zeroes = (int)floor(workNumber);
+	  zeroes = (int)floorl(workNumber);
 	}
     }
 
   if (flags & FLAGS_FLOAT_E)
     {
       /* Scale the number */
-      workNumber = guarded_log10(number);
+      workNumber = TrioLogarithm(number, base);
       if (trio_isinf(workNumber) == -1)
 	{
 	  exponent = 0;
@@ -2424,8 +2719,8 @@
 	}
       else
 	{
-	  exponent = (int)floor(workNumber);
-	  number /= pow(10.0, (double)exponent);
+	  exponent = (int)floorl(workNumber);
+	  number /= powl(dblBase, (trio_long_double_t)exponent);
 	  isExponentNegative = (exponent < 0);
 	  uExponent = (isExponentNegative) ? -exponent : exponent;
 	  /* No thousand separators */
@@ -2433,140 +2728,107 @@
 	}
     }
 
+  integerNumber = floorl(number);
+  fractionNumber = number - integerNumber;
+  
   /*
    * Truncated number.
    *
-   * precision is number of significant digits for FLOAT_G
-   * and number of fractional digits for others
+   * Precision is number of significant digits for FLOAT_G
+   * and number of fractional digits for others.
    */
-  integerDigits = (floor(number) > DBL_EPSILON)
-    ? 1 + (int)guarded_log10(floor(number))
+  integerDigits = (integerNumber > epsilon)
+    ? 1 + (int)TrioLogarithm(integerNumber, base)
     : 1;
   fractionDigits = ((flags & FLAGS_FLOAT_G) && (zeroes == 0))
     ? precision - integerDigits
     : zeroes + precision;
+
+  dblFractionBase = TrioPower(base, fractionDigits);
   
-  number = floor(0.5 + number * pow(dblBase, (double)fractionDigits));
-  workNumber = (isHex
-		? guarded_log16(0.5 + number)
-		: guarded_log10(0.5 + number));
-  if ((int)workNumber + 1 > integerDigits + 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--;
-	  uExponent -= (isExponentNegative) ? 1 : -1;
-	  number /= dblBase;
+	  exponent++;
+	  isExponentNegative = (exponent < 0);
+	  uExponent = (isExponentNegative) ? -exponent : exponent;
+	  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) */
-	  integerDigits++;
+	  integerNumber = floorl(number + 0.5);
+	  fractionNumber = 0.0;
+	  integerDigits = (integerNumber > epsilon)
+	    ? 1 + (int)TrioLogarithm(integerNumber, base)
+	    : 1;
 	}
     }
-  
-  /* Build the fraction part */
-  numberPointer = &numberBuffer[sizeof(numberBuffer) - 1];
-  *numberPointer = NIL;
-  onlyzero = TRUE;
-  for (i = 0; i < fractionDigits; i++)
-    {
-      *(--numberPointer) = digits[(int)fmod(number, dblBase)];
-      number = floor(number / dblBase);
 
-      if ((flags & FLAGS_FLOAT_G) && !(flags & FLAGS_ALTERNATIVE))
-        {
-          /* Prune trailing zeroes */
-          if (numberPointer[0] != digits[0])
-            onlyzero = FALSE;
-          else if (onlyzero && (numberPointer[0] == digits[0]))
-            numberPointer++;
-        }
+  /* 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
-        onlyzero = FALSE;
-    }
-  
-  /* Insert decimal point */
-  if ((flags & FLAGS_ALTERNATIVE) || ((fractionDigits > 0) && !onlyzero))
-    {
-      i = trio_length(internalDecimalPoint);
-      while (i> 0)
 	{
-	  *(--numberPointer) = internalDecimalPoint[--i];
+	  integerThreshold = integerDigits;
+	  fractionThreshold = fractionDigits - integerThreshold;
+	  fractionAdjust = 1.0;
 	}
     }
-  /* Insert the integer part and thousand separators */
-  charsPerThousand = (int)internalGrouping[0];
-  groupingIndex = 1;
-  for (i = 1; i < integerDigits + 1; i++)
+  else
     {
-      *(--numberPointer) = digits[(int)fmod(number, dblBase)];
-      number = floor(number / dblBase);
-      if (number < DBL_EPSILON)
-	break;
-
-      if ((i > 0)
-	  && ((flags & (FLAGS_FLOAT_E | FLAGS_QUOTE)) == FLAGS_QUOTE)
-	  && (charsPerThousand != NO_GROUPING)
-	  && (i % charsPerThousand == 0))
-	{
-	  /*
-	   * We are building the number from the least significant
-	   * to the most significant digit, so we have to copy the
-	   * thousand separator backwards
-	   */
-	  length = trio_length(internalThousandSeparator);
-	  integerDigits += length;
-	  if (((int)(numberPointer - numberBuffer) - length) > 0)
-	    {
-	      work = &internalThousandSeparator[length - 1];
-	      while (length-- > 0)
-		*(--numberPointer) = *work--;
-	    }
-
-	  /* Advance to next grouping number */
-	  if (charsPerThousand != NO_GROUPING)
-	    {
-	      switch (internalGrouping[groupingIndex])
-		{
-		case CHAR_MAX: /* Disable grouping */
-		  charsPerThousand = NO_GROUPING;
-		  break;
-		case 0: /* Repeat last group */
-		  break;
-		default:
-		  charsPerThousand = (int)internalGrouping[groupingIndex++];
-		  break;
-		}
-	    }
-	}
+      integerThreshold = INT_MAX;
+      fractionThreshold = INT_MAX;
     }
   
-  /* Build the exponent */
-  exponentDigits = 0;
-  if (flags & FLAGS_FLOAT_E)
-    {
-      exponentPointer = &exponentBuffer[sizeof(exponentBuffer) - 1];
-      *exponentPointer-- = NIL;
-      do {
-	*exponentPointer-- = digits[uExponent % base];
-	uExponent /= base;
-	exponentDigits++;
-      } while (uExponent);
-    }
-
   /*
    * Calculate expected width.
    *  sign + integer part + thousands separators + decimal point
    *  + fraction + exponent
    */
-  expectedWidth = trio_length(numberPointer);
-  if (isNegative || (flags & FLAGS_SHOWSIGN))
+  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), 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 +
-      ((exponentDigits > 1) ? sizeof("E+") : sizeof("E+0")) - 1;
+      ((requireTwoDigitExponent ? sizeof("E+0") : sizeof("E+")) - 1);
   if (isHex)
     expectedWidth += sizeof("0X") - 1;
   
@@ -2578,6 +2840,8 @@
 	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');
@@ -2605,17 +2869,101 @@
 	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 number */
-  for (i = 0; numberPointer[i]; i++)
+  
+  /* Output the integer part and thousand separators */
+  dblIntegerBase = 1.0 / TrioPower(base, integerDigits - 1);
+  for (i = 0; i < integerDigits; i++)
     {
-      self->OutStream(self, numberPointer[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)
     {
@@ -2626,12 +2974,14 @@
       self->OutStream(self, (isExponentNegative) ? '-' : '+');
 
       /* The exponent must contain at least two digits */
-      if (exponentDigits == 1)
+      if (requireTwoDigitExponent)
         self->OutStream(self, '0');
 
+      exponentBase = (int)TrioPower(base, exponentDigits - 1);
       for (i = 0; i < exponentDigits; i++)
 	{
-	  self->OutStream(self, exponentPointer[i + 1]);
+	  self->OutStream(self, digits[(uExponent / exponentBase) % base]);
+	  exponentBase /= base;
 	}
     }
   /* Output trailing spaces */
@@ -2651,17 +3001,18 @@
  *  This is the main engine for formatting output
  */
 TRIO_PRIVATE int
-TrioFormatProcess(trio_class_t *data,
-		  TRIO_CONST char *format,
-		  trio_parameter_t *parameters)
-
+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;
-  void *pointer;
+  trio_pointer_t pointer;
   unsigned long flags;
   int width;
   int precision;
@@ -2671,7 +3022,7 @@
   index = 0;
   i = 0;
 #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
-  mblen(NULL, 0);
+  (void)mblen(NULL, 0);
 #endif
   
   while (format[index])
@@ -2680,11 +3031,19 @@
       if (! isascii(format[index]))
 	{
 	  charlen = mblen(&format[index], MB_LEN_MAX);
-	  while (charlen-- > 0)
+	  /*
+	   * Only valid multibyte characters are handled here. Invalid
+	   * multibyte characters (charlen == -1) are handled as normal
+	   * characters.
+	   */
+	  if (charlen != -1)
 	    {
-	      data->OutStream(data, format[index++]);
+	      while (charlen-- > 0)
+		{
+		  data->OutStream(data, format[index++]);
+		}
+	      continue; /* while characters left in formatting string */
 	    }
-	  continue; /* while */
 	}
 #endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
       if (CHAR_IDENTIFIER == format[index])
@@ -2747,7 +3106,7 @@
 		  if (flags & FLAGS_WIDECHAR)
 		    {
 		      TrioWriteWideStringCharacter(data,
-						   (wchar_t)parameters[i].data.number.as_signed,
+						   (trio_wchar_t)parameters[i].data.number.as_signed,
 						   flags,
 						   NO_WIDTH);
 		    }
@@ -2770,11 +3129,8 @@
 		  break; /* FORMAT_CHAR */
 
 		case FORMAT_INT:
-		  if (base == NO_BASE)
-		    base = BASE_DECIMAL;
-
 		  TrioWriteNumber(data,
-				  parameters[i].data.number.as_signed,
+				  parameters[i].data.number.as_unsigned,
 				  flags,
 				  width,
 				  precision,
@@ -2883,7 +3239,7 @@
 		    {
 		      data->OutStream(data, '#');
 		      TrioWriteNumber(data,
-				      (trio_intmax_t)parameters[i].data.errorNumber,
+				      (trio_uintmax_t)parameters[i].data.errorNumber,
 				      flags,
 				      width,
 				      precision,
@@ -2940,10 +3296,12 @@
  * TrioFormatRef
  */
 TRIO_PRIVATE int
-TrioFormatRef(trio_reference_t *reference,
-	      TRIO_CONST char *format,
-	      va_list arglist,
-	      void **argarray)
+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];
@@ -2964,12 +3322,14 @@
  * TrioFormat
  */
 TRIO_PRIVATE int
-TrioFormat(void *destination,
+TrioFormat
+TRIO_ARGS6((destination, destinationSize, OutStream, format, arglist, argarray),
+	   trio_pointer_t destination,
 	   size_t destinationSize,
-	   void (*OutStream)(trio_class_t *, int),
+	   void (*OutStream) TRIO_PROTO((trio_class_t *, int)),
 	   TRIO_CONST char *format,
-	   va_list arglist,
-	   void **argarray)
+	   va_list *arglist,
+	   trio_pointer_t *argarray)
 {
   int status;
   trio_class_t data;
@@ -3007,14 +3367,17 @@
  * TrioOutStreamFile
  */
 TRIO_PRIVATE void
-TrioOutStreamFile(trio_class_t *self,
-		  int output)
+TrioOutStreamFile
+TRIO_ARGS2((self, output),
+	   trio_class_t *self,
+	   int output)
 {
-  FILE *file = (FILE *)self->location;
+  FILE *file;
 
   assert(VALID(self));
-  assert(VALID(file));
+  assert(VALID(self->location));
 
+  file = (FILE *)self->location;
   self->processed++;
   if (fputc(output, file) == EOF)
     {
@@ -3030,14 +3393,17 @@
  * TrioOutStreamFileDescriptor
  */
 TRIO_PRIVATE void
-TrioOutStreamFileDescriptor(trio_class_t *self,
-			    int output)
+TrioOutStreamFileDescriptor
+TRIO_ARGS2((self, output),
+	   trio_class_t *self,
+	   int output)
 {
-  int fd = *((int *)self->location);
+  int fd;
   char ch;
 
   assert(VALID(self));
 
+  fd = *((int *)self->location);
   ch = (char)output;
   self->processed++;
   if (write(fd, &ch, sizeof(char)) == -1)
@@ -3051,17 +3417,54 @@
 }
 
 /*************************************************************************
+ * 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_class_t *self,
-		    int output)
+TrioOutStreamString
+TRIO_ARGS2((self, output),
+	   trio_class_t *self,
+	   int output)
 {
-  char **buffer = (char **)self->location;
+  char **buffer;
 
   assert(VALID(self));
-  assert(VALID(buffer));
+  assert(VALID(self->location));
 
+  buffer = (char **)self->location;
   **buffer = (char)output;
   (*buffer)++;
   self->processed++;
@@ -3072,14 +3475,17 @@
  * TrioOutStreamStringMax
  */
 TRIO_PRIVATE void
-TrioOutStreamStringMax(trio_class_t *self,
-		       int output)
+TrioOutStreamStringMax
+TRIO_ARGS2((self, output),
+	   trio_class_t *self,
+	   int output)
 {
   char **buffer;
 
   assert(VALID(self));
+  assert(VALID(self->location));
+  
   buffer = (char **)self->location;
-  assert(VALID(buffer));
 
   if (self->processed < self->max)
     {
@@ -3094,8 +3500,10 @@
  * TrioOutStreamStringDynamic
  */
 TRIO_PRIVATE void
-TrioOutStreamStringDynamic(trio_class_t *self,
-			   int output)
+TrioOutStreamStringDynamic
+TRIO_ARGS2((self, output),
+	   trio_class_t *self,
+	   int output)
 {
   assert(VALID(self));
   assert(VALID(self->location));
@@ -3135,17 +3543,19 @@
    @return Number of printed characters.
  */
 TRIO_PUBLIC int
-trio_printf(TRIO_CONST char *format,
-	    ...)
+trio_printf
+TRIO_VARGS2((format, va_alist),
+	    TRIO_CONST char *format,
+	    TRIO_VA_DECL)
 {
   int status;
   va_list args;
 
   assert(VALID(format));
   
-  va_start(args, format);
-  status = TrioFormat(stdout, 0, TrioOutStreamFile, format, args, NULL);
-  va_end(args);
+  TRIO_VA_START(args, format);
+  status = TrioFormat(stdout, 0, TrioOutStreamFile, format, &args, NULL);
+  TRIO_VA_END(args);
   return status;
 }
 
@@ -3157,12 +3567,14 @@
    @return Number of printed characters.
  */
 TRIO_PUBLIC int
-trio_vprintf(TRIO_CONST char *format,
-	     va_list args)
+trio_vprintf
+TRIO_ARGS2((format, args),
+	   TRIO_CONST char *format,
+	   va_list args)
 {
   assert(VALID(format));
 
-  return TrioFormat(stdout, 0, TrioOutStreamFile, format, args, NULL);
+  return TrioFormat(stdout, 0, TrioOutStreamFile, format, &args, NULL);
 }
 
 /**
@@ -3173,14 +3585,14 @@
    @return Number of printed characters.
  */
 TRIO_PUBLIC int
-trio_printfv(TRIO_CONST char *format,
-	     void ** args)
+trio_printfv
+TRIO_ARGS2((format, args),
+	   TRIO_CONST char *format,
+	   trio_pointer_t * args)
 {
-  va_list dummy;
-  
   assert(VALID(format));
 
-  return TrioFormat(stdout, 0, TrioOutStreamFile, format, dummy, args);
+  return TrioFormat(stdout, 0, TrioOutStreamFile, format, NULL, args);
 }
 
 /*************************************************************************
@@ -3196,9 +3608,11 @@
    @return Number of printed characters.
  */
 TRIO_PUBLIC int
-trio_fprintf(FILE *file,
-	     TRIO_CONST char *format,
-	     ...)
+trio_fprintf
+TRIO_VARGS3((file, format, va_alist),
+	    FILE *file,
+	    TRIO_CONST char *format,
+	    TRIO_VA_DECL)
 {
   int status;
   va_list args;
@@ -3206,9 +3620,9 @@
   assert(VALID(file));
   assert(VALID(format));
   
-  va_start(args, format);
-  status = TrioFormat(file, 0, TrioOutStreamFile, format, args, NULL);
-  va_end(args);
+  TRIO_VA_START(args, format);
+  status = TrioFormat(file, 0, TrioOutStreamFile, format, &args, NULL);
+  TRIO_VA_END(args);
   return status;
 }
 
@@ -3221,14 +3635,16 @@
    @return Number of printed characters.
  */
 TRIO_PUBLIC int
-trio_vfprintf(FILE *file,
-	      TRIO_CONST char *format,
-	      va_list args)
+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);
+  return TrioFormat(file, 0, TrioOutStreamFile, format, &args, NULL);
 }
 
 /**
@@ -3240,16 +3656,16 @@
    @return Number of printed characters.
  */
 TRIO_PUBLIC int
-trio_fprintfv(FILE *file,
-	      TRIO_CONST char *format,
-	      void ** args)
+trio_fprintfv
+TRIO_ARGS3((file, format, args),
+	   FILE *file,
+	   TRIO_CONST char *format,
+	   trio_pointer_t * args)
 {
-  va_list dummy;
-  
   assert(VALID(file));
   assert(VALID(format));
   
-  return TrioFormat(file, 0, TrioOutStreamFile, format, dummy, args);
+  return TrioFormat(file, 0, TrioOutStreamFile, format, NULL, args);
 }
 
 /*************************************************************************
@@ -3265,18 +3681,20 @@
    @return Number of printed characters.
  */
 TRIO_PUBLIC int
-trio_dprintf(int fd,
-	     TRIO_CONST char *format,
-	     ...)
+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));
   
-  va_start(args, format);
-  status = TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, args, NULL);
-  va_end(args);
+  TRIO_VA_START(args, format);
+  status = TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, &args, NULL);
+  TRIO_VA_END(args);
   return status;
 }
 
@@ -3289,13 +3707,15 @@
    @return Number of printed characters.
  */
 TRIO_PUBLIC int
-trio_vdprintf(int fd,
-	      TRIO_CONST char *format,
-	      va_list args)
+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);
+  return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, &args, NULL);
 }
 
 /**
@@ -3307,15 +3727,77 @@
    @return Number of printed characters.
  */
 TRIO_PUBLIC int
-trio_dprintfv(int fd,
-	      TRIO_CONST char *format,
-	      void **args)
+trio_dprintfv
+TRIO_ARGS3((fd, format, args),
+	   int fd,
+	   TRIO_CONST char *format,
+	   trio_pointer_t *args)
 {
-  va_list dummy;
-  
   assert(VALID(format));
   
-  return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, dummy, args);
+  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);
 }
 
 /*************************************************************************
@@ -3331,9 +3813,11 @@
    @return Number of printed characters.
  */
 TRIO_PUBLIC int
-trio_sprintf(char *buffer,
-	     TRIO_CONST char *format,
-	     ...)
+trio_sprintf
+TRIO_VARGS3((buffer, format, va_alist),
+	    char *buffer,
+	    TRIO_CONST char *format,
+	    TRIO_VA_DECL)
 {
   int status;
   va_list args;
@@ -3341,10 +3825,10 @@
   assert(VALID(buffer));
   assert(VALID(format));
   
-  va_start(args, format);
-  status = TrioFormat(&buffer, 0, TrioOutStreamString, format, args, NULL);
+  TRIO_VA_START(args, format);
+  status = TrioFormat(&buffer, 0, TrioOutStreamString, format, &args, NULL);
   *buffer = NIL; /* Terminate with NIL character */
-  va_end(args);
+  TRIO_VA_END(args);
   return status;
 }
 
@@ -3357,16 +3841,18 @@
    @return Number of printed characters.
  */
 TRIO_PUBLIC int
-trio_vsprintf(char *buffer,
-	      TRIO_CONST char *format,
-	      va_list args)
+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);
+  status = TrioFormat(&buffer, 0, TrioOutStreamString, format, &args, NULL);
   *buffer = NIL;
   return status;
 }
@@ -3380,17 +3866,18 @@
    @return Number of printed characters.
  */
 TRIO_PUBLIC int
-trio_sprintfv(char *buffer,
-	      TRIO_CONST char *format,
-	      void **args)
+trio_sprintfv
+TRIO_ARGS3((buffer, format, args),
+	   char *buffer,
+	   TRIO_CONST char *format,
+	   trio_pointer_t *args)
 {
   int status;
-  va_list dummy;
 
   assert(VALID(buffer));
   assert(VALID(format));
 
-  status = TrioFormat(&buffer, 0, TrioOutStreamString, format, dummy, args);
+  status = TrioFormat(&buffer, 0, TrioOutStreamString, format, NULL, args);
   *buffer = NIL;
   return status;
 }
@@ -3409,10 +3896,12 @@
    @return Number of printed characters.
  */
 TRIO_PUBLIC int
-trio_snprintf(char *buffer,
-	      size_t max,
-	      TRIO_CONST char *format,
-	      ...)
+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;
@@ -3420,12 +3909,12 @@
   assert(VALID(buffer));
   assert(VALID(format));
 
-  va_start(args, format);
+  TRIO_VA_START(args, format);
   status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
-		      TrioOutStreamStringMax, format, args, NULL);
+		      TrioOutStreamStringMax, format, &args, NULL);
   if (max > 0)
     *buffer = NIL;
-  va_end(args);
+  TRIO_VA_END(args);
   return status;
 }
 
@@ -3439,10 +3928,12 @@
    @return Number of printed characters.
  */
 TRIO_PUBLIC int
-trio_vsnprintf(char *buffer,
-	       size_t max,
-	       TRIO_CONST char *format,
-	       va_list args)
+trio_vsnprintf
+TRIO_ARGS4((buffer, max, format, args),
+	   char *buffer,
+	   size_t max,
+	   TRIO_CONST char *format,
+	   va_list args)
 {
   int status;
 
@@ -3450,7 +3941,7 @@
   assert(VALID(format));
 
   status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
-		      TrioOutStreamStringMax, format, args, NULL);
+		      TrioOutStreamStringMax, format, &args, NULL);
   if (max > 0)
     *buffer = NIL;
   return status;
@@ -3466,19 +3957,20 @@
    @return Number of printed characters.
  */
 TRIO_PUBLIC int
-trio_snprintfv(char *buffer,
-	       size_t max,
-	       TRIO_CONST char *format,
-	       void **args)
+trio_snprintfv
+TRIO_ARGS4((buffer, max, format, args),
+	   char *buffer,
+	   size_t max,
+	   TRIO_CONST char *format,
+	   trio_pointer_t *args)
 {
   int status;
-  va_list dummy;
 
   assert(VALID(buffer));
   assert(VALID(format));
 
   status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
-		      TrioOutStreamStringMax, format, dummy, args);
+		      TrioOutStreamStringMax, format, NULL, args);
   if (max > 0)
     *buffer = NIL;
   return status;
@@ -3490,16 +3982,18 @@
  * character at the end of buffer.
  */
 TRIO_PUBLIC int
-trio_snprintfcat(char *buffer,
-		 size_t max,
-		 TRIO_CONST char *format,
-		 ...)
+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;
 
-  va_start(args, format);
+  TRIO_VA_START(args, format);
 
   assert(VALID(buffer));
   assert(VALID(format));
@@ -3508,27 +4002,30 @@
   buffer = &buffer[buf_len];
 
   status = TrioFormat(&buffer, max - 1 - buf_len,
-		      TrioOutStreamStringMax, format, args, NULL);
-  va_end(args);
+		      TrioOutStreamStringMax, format, &args, NULL);
+  TRIO_VA_END(args);
   *buffer = NIL;
   return status;
 }
 
 TRIO_PUBLIC int
-trio_vsnprintfcat(char *buffer,
-		  size_t max,
-		  TRIO_CONST char *format,
-		  va_list args)
+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);
+		      TrioOutStreamStringMax, format, &args, NULL);
   *buffer = NIL;
   return status;
 }
@@ -3539,8 +4036,10 @@
 
 /* Deprecated */
 TRIO_PUBLIC char *
-trio_aprintf(TRIO_CONST char *format,
-	     ...)
+trio_aprintf
+TRIO_VARGS2((format, va_alist),
+	    TRIO_CONST char *format,
+	    TRIO_VA_DECL)
 {
   va_list args;
   trio_string_t *info;
@@ -3551,10 +4050,10 @@
   info = trio_xstring_duplicate("");
   if (info)
     {
-      va_start(args, format);
+      TRIO_VA_START(args, format);
       (void)TrioFormat(info, 0, TrioOutStreamStringDynamic,
-		       format, args, NULL);
-      va_end(args);
+		       format, &args, NULL);
+      TRIO_VA_END(args);
 
       trio_string_terminate(info);
       result = trio_string_extract(info);
@@ -3565,8 +4064,10 @@
 
 /* Deprecated */
 TRIO_PUBLIC char *
-trio_vaprintf(TRIO_CONST char *format,
-	      va_list args)
+trio_vaprintf
+TRIO_ARGS2((format, args),
+	   TRIO_CONST char *format,
+	   va_list args)
 {
   trio_string_t *info;
   char *result = NULL;
@@ -3577,7 +4078,7 @@
   if (info)
     {
       (void)TrioFormat(info, 0, TrioOutStreamStringDynamic,
-		       format, args, NULL);
+		       format, &args, NULL);
       trio_string_terminate(info);
       result = trio_string_extract(info);
       trio_string_destroy(info);
@@ -3586,9 +4087,11 @@
 }
 
 TRIO_PUBLIC int
-trio_asprintf(char **result,
-	      TRIO_CONST char *format,
-	      ...)
+trio_asprintf
+TRIO_VARGS3((result, format, va_alist),
+	    char **result,
+	    TRIO_CONST char *format,
+	    TRIO_VA_DECL)
 {
   va_list args;
   int status;
@@ -3605,10 +4108,10 @@
     }
   else
     {
-      va_start(args, format);
+      TRIO_VA_START(args, format);
       status = TrioFormat(info, 0, TrioOutStreamStringDynamic,
-			  format, args, NULL);
-      va_end(args);
+			  format, &args, NULL);
+      TRIO_VA_END(args);
       if (status >= 0)
 	{
 	  trio_string_terminate(info);
@@ -3620,9 +4123,11 @@
 }
 
 TRIO_PUBLIC int
-trio_vasprintf(char **result,
-	       TRIO_CONST char *format,
-	       va_list args)
+trio_vasprintf
+TRIO_ARGS3((result, format, args),
+	   char **result,
+	   TRIO_CONST char *format,
+	   va_list args)
 {
   int status;
   trio_string_t *info;
@@ -3639,7 +4144,7 @@
   else
     {
       status = TrioFormat(info, 0, TrioOutStreamStringDynamic,
-			  format, args, NULL);
+			  format, &args, NULL);
       if (status >= 0)
 	{
 	  trio_string_terminate(info);
@@ -3658,7 +4163,6 @@
  *
  ************************************************************************/
 
-
 #if defined(TRIO_DOCUMENTATION)
 # include "doc/doc_register.h"
 #endif
@@ -3667,6 +4171,8 @@
    @{
 */
 
+#if TRIO_EXTENSION
+
 /*************************************************************************
  * trio_register
  */
@@ -3678,9 +4184,11 @@
    @param name
    @return Handle.
  */
-TRIO_PUBLIC void *
-trio_register(trio_callback_t callback,
-	      TRIO_CONST char *name)
+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;
@@ -3738,14 +4246,18 @@
       if (internalLeaveCriticalRegion)
 	(void)internalLeaveCriticalRegion(NULL);
     }
-  return def;
+  return (trio_pointer_t)def;
 }
 
-/*************************************************************************
- * trio_unregister [public]
+/**
+   Unregister an existing user-defined specifier.
+
+   @param handle
  */
 void
-trio_unregister(void *handle)
+trio_unregister
+TRIO_ARGS1((handle),
+	   trio_pointer_t handle)
 {
   trio_userdef_t *self = (trio_userdef_t *)handle;
   trio_userdef_t *def;
@@ -3778,9 +4290,13 @@
  * trio_get_format [public]
  */
 TRIO_CONST char *
-trio_get_format(void *ref)
+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);
 }
@@ -3788,10 +4304,14 @@
 /*************************************************************************
  * trio_get_argument [public]
  */
-void *
-trio_get_argument(void *ref)
+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;
 }
@@ -3800,14 +4320,18 @@
  * trio_get_width / trio_set_width [public]
  */
 int
-trio_get_width(void *ref)
+trio_get_width
+TRIO_ARGS1((ref),
+	   trio_pointer_t ref)
 {
   return ((trio_reference_t *)ref)->parameter->width;
 }
 
 void
-trio_set_width(void *ref,
-	       int width)
+trio_set_width
+TRIO_ARGS2((ref, width),
+	   trio_pointer_t ref,
+	   int width)
 {
   ((trio_reference_t *)ref)->parameter->width = width;
 }
@@ -3816,14 +4340,18 @@
  * trio_get_precision / trio_set_precision [public]
  */
 int
-trio_get_precision(void *ref)
+trio_get_precision
+TRIO_ARGS1((ref),
+	   trio_pointer_t ref)
 {
   return (((trio_reference_t *)ref)->parameter->precision);
 }
 
 void
-trio_set_precision(void *ref,
-		   int precision)
+trio_set_precision
+TRIO_ARGS2((ref, precision),
+	   trio_pointer_t ref,
+	   int precision)
 {
   ((trio_reference_t *)ref)->parameter->precision = precision;
 }
@@ -3832,14 +4360,18 @@
  * trio_get_base / trio_set_base [public]
  */
 int
-trio_get_base(void *ref)
+trio_get_base
+TRIO_ARGS1((ref),
+	   trio_pointer_t ref)
 {
   return (((trio_reference_t *)ref)->parameter->base);
 }
 
 void
-trio_set_base(void *ref,
-	      int base)
+trio_set_base
+TRIO_ARGS2((ref, base),
+	   trio_pointer_t ref,
+	   int base)
 {
   ((trio_reference_t *)ref)->parameter->base = base;
 }
@@ -3848,14 +4380,18 @@
  * trio_get_long / trio_set_long [public]
  */
 int
-trio_get_long(void *ref)
+trio_get_long
+TRIO_ARGS1((ref),
+	   trio_pointer_t ref)
 {
   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LONG);
 }
 
 void
-trio_set_long(void *ref,
-	      int is_long)
+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;
@@ -3867,14 +4403,18 @@
  * trio_get_longlong / trio_set_longlong [public]
  */
 int
-trio_get_longlong(void *ref)
+trio_get_longlong
+TRIO_ARGS1((ref),
+	   trio_pointer_t ref)
 {
   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_QUAD);
 }
 
 void
-trio_set_longlong(void *ref,
-		  int is_longlong)
+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;
@@ -3886,14 +4426,18 @@
  * trio_get_longdouble / trio_set_longdouble [public]
  */
 int
-trio_get_longdouble(void *ref)
+trio_get_longdouble
+TRIO_ARGS1((ref),
+	   trio_pointer_t ref)
 {
   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LONGDOUBLE);
 }
 
 void
-trio_set_longdouble(void *ref,
-		    int is_longdouble)
+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;
@@ -3905,14 +4449,18 @@
  * trio_get_short / trio_set_short [public]
  */
 int
-trio_get_short(void *ref)
+trio_get_short
+TRIO_ARGS1((ref),
+	   trio_pointer_t ref)
 {
   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHORT);
 }
 
 void
-trio_set_short(void *ref,
-	       int is_short)
+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;
@@ -3924,14 +4472,18 @@
  * trio_get_shortshort / trio_set_shortshort [public]
  */
 int
-trio_get_shortshort(void *ref)
+trio_get_shortshort
+TRIO_ARGS1((ref),
+	   trio_pointer_t ref)
 {
   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHORTSHORT);
 }
 
 void
-trio_set_shortshort(void *ref,
-	       int is_shortshort)
+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;
@@ -3943,14 +4495,18 @@
  * trio_get_alternative / trio_set_alternative [public]
  */
 int
-trio_get_alternative(void *ref)
+trio_get_alternative
+TRIO_ARGS1((ref),
+	   trio_pointer_t ref)
 {
   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_ALTERNATIVE);
 }
 
 void
-trio_set_alternative(void *ref,
-		     int is_alternative)
+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;
@@ -3962,14 +4518,18 @@
  * trio_get_alignment / trio_set_alignment [public]
  */
 int
-trio_get_alignment(void *ref)
+trio_get_alignment
+TRIO_ARGS1((ref),
+	   trio_pointer_t ref)
 {
   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LEFTADJUST);
 }
 
 void
-trio_set_alignment(void *ref,
-		   int is_leftaligned)
+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;
@@ -3981,14 +4541,18 @@
  * trio_get_spacing /trio_set_spacing [public]
  */
 int
-trio_get_spacing(void *ref)
+trio_get_spacing
+TRIO_ARGS1((ref),
+	   trio_pointer_t ref)
 {
   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SPACE);
 }
 
 void
-trio_set_spacing(void *ref,
-		 int is_space)
+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;
@@ -4000,14 +4564,18 @@
  * trio_get_sign / trio_set_sign [public]
  */
 int
-trio_get_sign(void *ref)
+trio_get_sign
+TRIO_ARGS1((ref),
+	   trio_pointer_t ref)
 {
   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHOWSIGN);
 }
 
 void
-trio_set_sign(void *ref,
-	      int is_sign)
+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;
@@ -4019,14 +4587,18 @@
  * trio_get_padding / trio_set_padding [public]
  */
 int
-trio_get_padding(void *ref)
+trio_get_padding
+TRIO_ARGS1((ref),
+	   trio_pointer_t ref)
 {
   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_NILPADDING);
 }
 
 void
-trio_set_padding(void *ref,
-		 int is_padding)
+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;
@@ -4038,14 +4610,18 @@
  * trio_get_quote / trio_set_quote [public]
  */
 int
-trio_get_quote(void *ref)
+trio_get_quote
+TRIO_ARGS1((ref),
+	   trio_pointer_t ref)
 {
   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_QUOTE);
 }
 
 void
-trio_set_quote(void *ref,
-	       int is_quote)
+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;
@@ -4057,14 +4633,18 @@
  * trio_get_upper / trio_set_upper [public]
  */
 int
-trio_get_upper(void *ref)
+trio_get_upper
+TRIO_ARGS1((ref),
+	   trio_pointer_t ref)
 {
   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_UPPER);
 }
 
 void
-trio_set_upper(void *ref,
-	       int is_upper)
+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;
@@ -4077,14 +4657,18 @@
  */
 #if TRIO_C99
 int
-trio_get_largest(void *ref)
+trio_get_largest
+TRIO_ARGS1((ref),
+	   trio_pointer_t ref)
 {
   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_INTMAX_T);
 }
 
 void
-trio_set_largest(void *ref,
-		 int is_largest)
+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;
@@ -4097,14 +4681,18 @@
  * trio_get_ptrdiff / trio_set_ptrdiff [public]
  */
 int
-trio_get_ptrdiff(void *ref)
+trio_get_ptrdiff
+TRIO_ARGS1((ref),
+	   trio_pointer_t ref)
 {
   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_PTRDIFF_T);
 }
 
 void
-trio_set_ptrdiff(void *ref,
-		 int is_ptrdiff)
+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;
@@ -4117,14 +4705,18 @@
  */
 #if TRIO_C99
 int
-trio_get_size(void *ref)
+trio_get_size
+TRIO_ARGS1((ref),
+	   trio_pointer_t ref)
 {
   return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SIZE_T);
 }
 
 void
-trio_set_size(void *ref,
-	      int is_size)
+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;
@@ -4137,13 +4729,15 @@
  * trio_print_int [public]
  */
 void
-trio_print_int(void *ref,
-	       int number)
+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_intmax_t)number,
+		  (trio_uintmax_t)number,
 		  self->parameter->flags,
 		  self->parameter->width,
 		  self->parameter->precision,
@@ -4154,13 +4748,15 @@
  * trio_print_uint [public]
  */
 void
-trio_print_uint(void *ref,
-		unsigned int number)
+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_intmax_t)number,
+		  (trio_uintmax_t)number,
 		  self->parameter->flags | FLAGS_UNSIGNED,
 		  self->parameter->width,
 		  self->parameter->precision,
@@ -4171,8 +4767,10 @@
  * trio_print_double [public]
  */
 void
-trio_print_double(void *ref,
-		  double number)
+trio_print_double
+TRIO_ARGS2((ref, number),
+	   trio_pointer_t ref,
+	   double number)
 {
   trio_reference_t *self = (trio_reference_t *)ref;
 
@@ -4188,8 +4786,10 @@
  * trio_print_string [public]
  */
 void
-trio_print_string(void *ref,
-		  char *string)
+trio_print_string
+TRIO_ARGS2((ref, string),
+	   trio_pointer_t ref,
+	   char *string)
 {
   trio_reference_t *self = (trio_reference_t *)ref;
 
@@ -4201,11 +4801,66 @@
 }
 
 /*************************************************************************
+ * 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(void *ref,
-		   void *pointer)
+trio_print_pointer
+TRIO_ARGS2((ref, pointer),
+	   trio_pointer_t ref,
+	   trio_pointer_t pointer)
 {
   trio_reference_t *self = (trio_reference_t *)ref;
   unsigned long flags;
@@ -4223,7 +4878,7 @@
        * 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
-       * optimising compiler). The (char *) casting is done
+       * optimizing compiler). The (char *) casting is done
        * to please ANSI C++.
        */
       number = (trio_uintmax_t)((char *)pointer - (char *)0);
@@ -4233,7 +4888,7 @@
       flags |= (FLAGS_UNSIGNED | FLAGS_ALTERNATIVE |
 	        FLAGS_NILPADDING);
       TrioWriteNumber(self->data,
-		      (trio_intmax_t)number,
+		      number,
 		      flags,
 		      POINTER_WIDTH,
 		      NO_PRECISION,
@@ -4241,67 +4896,110 @@
     }
 }
 
-/*************************************************************************
- * trio_print_ref [public]
- */
-int
-trio_print_ref(void *ref,
-	       TRIO_CONST char *format,
-	       ...)
-{
-  int status;
-  va_list arglist;
-
-  assert(VALID(format));
-  
-  va_start(arglist, format);
-  status = TrioFormatRef((trio_reference_t *)ref, format, arglist, NULL);
-  va_end(arglist);
-  return status;
-}
-
-/*************************************************************************
- * trio_vprint_ref [public]
- */
-int
-trio_vprint_ref(void *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(void *ref,
-		TRIO_CONST char *format,
-		void **argarray)
-{
-  va_list dummy;
-  
-  assert(VALID(format));
-  
-  return TrioFormatRef((trio_reference_t *)ref, format, dummy, argarray);
-}
-
 /** @} 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_class_t *self)
+TrioSkipWhitespaces
+TRIO_ARGS1((self),
+	   trio_class_t *self)
 {
   int ch;
 
@@ -4318,7 +5016,7 @@
  */
 #if TRIO_EXTENSION
 TRIO_PRIVATE void
-TrioGetCollation(void)
+TrioGetCollation(TRIO_NOARGS)
 {
   int i;
   int j;
@@ -4351,10 +5049,12 @@
  *  multibyte
  */
 TRIO_PRIVATE int
-TrioGetCharacterClass(TRIO_CONST char *format,
-		      int *indexPointer,
-		      unsigned long *flagsPointer,
-		      int *characterclass)
+TrioGetCharacterClass
+TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass),
+	   TRIO_CONST char *format,
+	   int *indexPointer,
+	   unsigned long *flagsPointer,
+	   int *characterclass)
 {
   int index = *indexPointer;
   int i;
@@ -4463,7 +5163,7 @@
 	    
 		if (internalCollationUnconverted)
 		  {
-		    /* Lazy evalutation of collation array */
+		    /* Lazy evaluation of collation array */
 		    TrioGetCollation();
 		    internalCollationUnconverted = FALSE;
 		  }
@@ -4608,16 +5308,19 @@
  * strtoul, because we must handle 'long long' and thousand separators.
  */
 TRIO_PRIVATE BOOLEAN_T
-TrioReadNumber(trio_class_t *self,
-	       trio_uintmax_t *target,
-	       unsigned long flags,
-	       int width,
-	       int base)
+TrioReadNumber
+TRIO_ARGS5((self, target, flags, width, base),
+	   trio_class_t *self,
+	   trio_uintmax_t *target,
+	   unsigned long 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));
@@ -4717,16 +5420,17 @@
             
       number *= base;
       number += digit;
+      gotNumber = TRUE; /* we need at least one digit */
 
       self->InStream(self, NULL);
     }
 
   /* Was anything read at all? */
-  if (self->processed == count)
+  if (!gotNumber)
     return FALSE;
   
   if (target)
-    *target = (isNegative) ? -number : number;
+    *target = (isNegative) ? -((trio_intmax_t)number) : number;
   return TRUE;
 }
 
@@ -4734,10 +5438,12 @@
  * TrioReadChar
  */
 TRIO_PRIVATE int
-TrioReadChar(trio_class_t *self,
-	     char *target,
-	     unsigned long flags,
-	     int width)
+TrioReadChar
+TRIO_ARGS4((self, target, flags, width),
+	   trio_class_t *self,
+	   char *target,
+	   unsigned long flags,
+	   int width)
 {
   int i;
   char ch;
@@ -4798,10 +5504,12 @@
  * TrioReadString
  */
 TRIO_PRIVATE BOOLEAN_T
-TrioReadString(trio_class_t *self,
-	       char *target,
-	       unsigned long flags,
-	       int width)
+TrioReadString
+TRIO_ARGS4((self, target, flags, width),
+	   trio_class_t *self,
+	   char *target,
+	   unsigned long flags,
+	   int width)
 {
   int i;
   
@@ -4819,7 +5527,7 @@
        (! ((self->current == EOF) || isspace(self->current)));
        i++)
     {
-      if (TrioReadChar(self, &target[i], flags, 1) == 0)
+      if (TrioReadChar(self, (target ? &target[i] : 0), flags, 1) == 0)
 	break; /* for */
     }
   if (target)
@@ -4832,16 +5540,18 @@
  */
 #if TRIO_WIDECHAR
 TRIO_PRIVATE int
-TrioReadWideChar(trio_class_t *self,
-		 wchar_t *target,
-		 unsigned long flags,
-		 int width)
+TrioReadWideChar
+TRIO_ARGS4((self, target, flags, width),
+	   trio_class_t *self,
+	   trio_wchar_t *target,
+	   unsigned long flags,
+	   int width)
 {
   int i;
   int j;
   int size;
   int amount = 0;
-  wchar_t wch;
+  trio_wchar_t wch;
   char buffer[MB_LEN_MAX + 1];
   
   assert(VALID(self));
@@ -4891,10 +5601,12 @@
  */
 #if TRIO_WIDECHAR
 TRIO_PRIVATE BOOLEAN_T
-TrioReadWideString(trio_class_t *self,
-		   wchar_t *target,
-		   unsigned long flags,
-		   int width)
+TrioReadWideString
+TRIO_ARGS4((self, target, flags, width),
+	   trio_class_t *self,
+	   trio_wchar_t *target,
+	   unsigned long flags,
+	   int width)
 {
   int i;
   int size;
@@ -4905,7 +5617,7 @@
   TrioSkipWhitespaces(self);
 
 #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
-  mblen(NULL, 0);
+  (void)mblen(NULL, 0);
 #endif
   
   /*
@@ -4935,11 +5647,13 @@
  * FIXME: characterclass does not work with multibyte characters
  */
 TRIO_PRIVATE BOOLEAN_T
-TrioReadGroup(trio_class_t *self,
-	      char *target,
-	      int *characterclass,
-	      unsigned long flags,
-	      int width)
+TrioReadGroup
+TRIO_ARGS5((self, target, characterclass, flags, width),
+	   trio_class_t *self,
+	   char *target,
+	   int *characterclass,
+	   unsigned long flags,
+	   int width)
 {
   int ch;
   int i;
@@ -4969,20 +5683,25 @@
  *
  * FIXME:
  *  add long double
+ *  handle base
  */
 TRIO_PRIVATE BOOLEAN_T
-TrioReadDouble(trio_class_t *self,
-	       double *target,
-	       unsigned long flags,
-	       int width)
+TrioReadDouble
+TRIO_ARGS4((self, target, flags, width),
+	   trio_class_t *self,
+	   trio_pointer_t target,
+	   unsigned long flags,
+	   int width)
 {
   int ch;
-  char doubleString[512] = "";
+  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;
   
@@ -5024,25 +5743,46 @@
       if (trio_equal(&doubleString[start], INFINITE_UPPER) ||
 	  trio_equal(&doubleString[start], LONG_INFINITE_UPPER))
 	{
-	  *target = ((start == 1 && doubleString[0] == '-'))
-	    ? trio_ninf()
-	    : trio_pinf();
+	  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 - */
-	  *target = trio_nan();
+	  if (flags & FLAGS_LONGDOUBLE)
+	    {
+	      *((trio_long_double_t *)target) = trio_nan();
+	    }
+	  else
+	    {
+	      *((double *)target) = trio_nan();
+	    }
 	  return TRUE;
 	}
       return FALSE;
-      
-    default:
-      break;
-    }
-  
-  if (ch == '0')
-    {
+
+    case '0':
       doubleString[index++] = (char)ch;
       self->InStream(self, &ch);
       if (toupper(ch) == 'X')
@@ -5051,7 +5791,12 @@
 	  doubleString[index++] = (char)ch;
 	  self->InStream(self, &ch);
 	}
+      break;
+      
+    default:
+      break;
     }
+  
   while ((ch != EOF) && (index - start < width))
     {
       /* Integer part */
@@ -5110,13 +5855,16 @@
 
   if ((index == start) || (*doubleString == NIL))
     return FALSE;
+
+  doubleString[index] = 0;
   
   if (flags & FLAGS_LONGDOUBLE)
-/*     *longdoublePointer = trio_to_long_double()*/
-    return FALSE; /* FIXME: Remove when long double is implemented */
+    {
+      *((trio_long_double_t *)target) = trio_to_long_double(doubleString, NULL);
+    }
   else
     {
-      *target = trio_to_double(doubleString, NULL);
+      *((double *)target) = trio_to_double(doubleString, NULL);
     }
   return TRUE;
 }
@@ -5125,9 +5873,11 @@
  * TrioReadPointer
  */
 TRIO_PRIVATE BOOLEAN_T
-TrioReadPointer(trio_class_t *self,
-		void **target,
-		unsigned long flags)
+TrioReadPointer
+TRIO_ARGS3((self, target, flags),
+	   trio_class_t *self,
+	   trio_pointer_t *target,
+	   unsigned long flags)
 {
   trio_uintmax_t number;
   char buffer[sizeof(internalNullString)];
@@ -5169,9 +5919,11 @@
  * TrioScanProcess
  */
 TRIO_PRIVATE int
-TrioScanProcess(trio_class_t *data,
-		TRIO_CONST char *format,
-		trio_parameter_t *parameters)
+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;
@@ -5184,7 +5936,7 @@
   unsigned long flags;
   int width;
   int base;
-  void *pointer;
+  trio_pointer_t pointer;
 
   assignment = 0;
   i = 0;
@@ -5192,7 +5944,7 @@
   data->InStream(data, &ch);
 
 #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
-  mblen(NULL, 0);
+  (void)mblen(NULL, 0);
 #endif
 
   while (format[index])
@@ -5201,20 +5953,26 @@
       if (! isascii(format[index]))
 	{
 	  charlen = mblen(&format[index], MB_LEN_MAX);
-	  /* Compare multibyte characters in format string */
-	  for (cnt = 0; cnt < charlen - 1; cnt++)
+	  if (charlen != -1)
 	    {
-	      if (ch != format[index + cnt])
+	      /* Compare multibyte characters in format string */
+	      for (cnt = 0; cnt < charlen - 1; cnt++)
 		{
-		  return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
+		  if (ch != format[index + cnt])
+		    {
+		      return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
+		    }
+		  data->InStream(data, &ch);
 		}
-	      data->InStream(data, &ch);
+	      continue; /* while characters left in formatting string */
 	    }
-	  continue; /* while */
 	}
 #endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
-      if (EOF == ch)
-	return EOF;
+      
+      if ((EOF == ch) && (parameters[i].type != FORMAT_COUNT))
+	{
+	  return (assignment > 0) ? assignment : EOF;
+	}
       
       if (CHAR_IDENTIFIER == format[index])
 	{
@@ -5266,10 +6024,11 @@
 				    width,
 				    base))
 		  return assignment;
-		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)
@@ -5321,20 +6080,34 @@
 				      width))
 		    return assignment;
 		}
-	      assignment++;
+	      if (!(flags & FLAGS_IGNORE))
+		assignment++;
 	      break; /* FORMAT_STRING */
-	      
-	    case FORMAT_DOUBLE:
-	      if (!TrioReadDouble(data,
-				  (flags & FLAGS_IGNORE)
-				  ? NULL
-				  : parameters[i].data.doublePointer,
-				  flags,
-				  width))
-		return assignment;
-	      assignment++;
-	      break; /* FORMAT_DOUBLE */
 
+	    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];
@@ -5364,44 +6137,48 @@
 				   flags,
 				   parameters[i].width))
 		  return assignment;
-		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)data->committed;
+		    *(size_t *)pointer = (size_t)count;
 		  else
 #endif
 #if defined(QUALIFIER_PTRDIFF_T)
 		  if (flags & FLAGS_PTRDIFF_T)
-		    *(ptrdiff_t *)pointer = (ptrdiff_t)data->committed;
+		    *(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)data->committed;
+		    *(trio_intmax_t *)pointer = (trio_intmax_t)count;
 		  else
 #endif
 		  if (flags & FLAGS_QUAD)
 		    {
-		      *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)data->committed;
+		      *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)count;
 		    }
 		  else if (flags & FLAGS_LONG)
 		    {
-		      *(long int *)pointer = (long int)data->committed;
+		      *(long int *)pointer = (long int)count;
 		    }
 		  else if (flags & FLAGS_SHORT)
 		    {
-		      *(short int *)pointer = (short int)data->committed;
+		      *(short int *)pointer = (short int)count;
 		    }
 		  else
 		    {
-		      *(int *)pointer = (int)data->committed;
+		      *(int *)pointer = (int)count;
 		    }
 		}
 	      break; /* FORMAT_COUNT */
@@ -5415,7 +6192,7 @@
 				       ? NULL
 				       : parameters[i].data.wstring,
 				       flags,
-				       (width == NO_WIDTH) ? 1 : width) > 0)
+				       (width == NO_WIDTH) ? 1 : width) == 0)
 		    return assignment;
 		}
 	      else
@@ -5426,25 +6203,27 @@
 				   ? NULL
 				   : parameters[i].data.string,
 				   flags,
-				   (width == NO_WIDTH) ? 1 : width) > 0)
+				   (width == NO_WIDTH) ? 1 : width) == 0)
 		    return assignment;
 		}
-	      assignment++;
+	      if (!(flags & FLAGS_IGNORE))
+		assignment++;
 	      break; /* FORMAT_CHAR */
-	      
+
 	    case FORMAT_POINTER:
 	      if (!TrioReadPointer(data,
 				   (flags & FLAGS_IGNORE)
 				   ? NULL
-				   : (void **)parameters[i].data.pointer,
+				   : (trio_pointer_t *)parameters[i].data.pointer,
 				   flags))
 		return assignment;
-	      assignment++;
+	      if (!(flags & FLAGS_IGNORE))
+		assignment++;
 	      break; /* FORMAT_POINTER */
-	      
+
 	    case FORMAT_PARAMETER:
 	      break; /* FORMAT_PARAMETER */
-	      
+
 	    default:
 	      return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
 	    }
@@ -5476,12 +6255,14 @@
  * TrioScan
  */
 TRIO_PRIVATE int
-TrioScan(TRIO_CONST void *source,
-	 size_t sourceSize,
-	 void (*InStream)(trio_class_t *, int *),
-	 TRIO_CONST char *format,
-	 va_list arglist,
-	 void **argarray)
+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];
@@ -5492,7 +6273,7 @@
 
   memset(&data, 0, sizeof(data));
   data.InStream = InStream;
-  data.location = (void *)source;
+  data.location = (trio_pointer_t)source;
   data.max = sourceSize;
   data.error = 0;
 
@@ -5519,8 +6300,10 @@
  * TrioInStreamFile
  */
 TRIO_PRIVATE void
-TrioInStreamFile(trio_class_t *self,
-		 int *intPointer)
+TrioInStreamFile
+TRIO_ARGS2((self, intPointer),
+	   trio_class_t *self,
+	   int *intPointer)
 {
   FILE *file = (FILE *)self->location;
 
@@ -5534,8 +6317,11 @@
 	? TRIO_ERROR_RETURN(TRIO_ERRNO, 0)
 	: TRIO_ERROR_RETURN(TRIO_EOF, 0);
     }
-  self->processed++;
-  self->committed++;
+  else
+    {
+      self->processed++;
+      self->committed++;
+    }
   
   if (VALID(intPointer))
     {
@@ -5547,8 +6333,10 @@
  * TrioInStreamFileDescriptor
  */
 TRIO_PRIVATE void
-TrioInStreamFileDescriptor(trio_class_t *self,
-			   int *intPointer)
+TrioInStreamFileDescriptor
+TRIO_ARGS2((self, intPointer),
+	   trio_class_t *self,
+	   int *intPointer)
 {
   int fd = *((int *)self->location);
   int size;
@@ -5566,8 +6354,47 @@
     {
       self->current = (size == 0) ? EOF : input;
     }
-  self->committed++;
-  self->processed++;
+  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))
     {
@@ -5579,22 +6406,28 @@
  * TrioInStreamString
  */
 TRIO_PRIVATE void
-TrioInStreamString(trio_class_t *self,
-		   int *intPointer)
+TrioInStreamString
+TRIO_ARGS2((self, intPointer),
+	   trio_class_t *self,
+	   int *intPointer)
 {
   unsigned char **buffer;
 
   assert(VALID(self));
-  assert(VALID(self->InStream));
   assert(VALID(self->location));
 
   buffer = (unsigned char **)self->location;
   self->current = (*buffer)[0];
   if (self->current == NIL)
-    self->current = EOF;
-  (*buffer)++;
-  self->processed++;
-  self->committed++;
+    {
+      self->current = EOF;
+    }
+  else
+    {
+      (*buffer)++;
+      self->processed++;
+      self->committed++;
+    }
   
   if (VALID(intPointer))
     {
@@ -5627,47 +6460,59 @@
    @return Number of scanned characters.
  */
 TRIO_PUBLIC int
-trio_scanf(TRIO_CONST char *format,
-	   ...)
+trio_scanf
+TRIO_VARGS2((format, va_alist),
+	    TRIO_CONST char *format,
+	    TRIO_VA_DECL)
 {
   int status;
   va_list args;
 
   assert(VALID(format));
   
-  va_start(args, format);
-  status = TrioScan(stdin, 0, TrioInStreamFile, format, args, NULL);
-  va_end(args);
+  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_CONST char *format,
-	    va_list args)
+trio_vscanf
+TRIO_ARGS2((format, args),
+	   TRIO_CONST char *format,
+	   va_list args)
 {
   assert(VALID(format));
   
-  return TrioScan(stdin, 0, TrioInStreamFile, format, args, NULL);
+  return TrioScan((trio_pointer_t)stdin, 0,
+		  TrioInStreamFile,
+		  format, &args, NULL);
 }
 
 TRIO_PUBLIC int
-trio_scanfv(TRIO_CONST char *format,
-	    void **args)
+trio_scanfv
+TRIO_ARGS2((format, args),
+	   TRIO_CONST char *format,
+	   trio_pointer_t *args)
 {
-  va_list dummy;
-  
   assert(VALID(format));
   
-  return TrioScan(stdin, 0, TrioInStreamFile, format, dummy, args);
+  return TrioScan((trio_pointer_t)stdin, 0,
+		  TrioInStreamFile,
+		  format, NULL, args);
 }
 
 /*************************************************************************
  * fscanf
  */
 TRIO_PUBLIC int
-trio_fscanf(FILE *file,
+trio_fscanf
+TRIO_VARGS3((file, format, va_alist),
+	    FILE *file,
 	    TRIO_CONST char *format,
-	    ...)
+	    TRIO_VA_DECL)
 {
   int status;
   va_list args;
@@ -5675,84 +6520,166 @@
   assert(VALID(file));
   assert(VALID(format));
   
-  va_start(args, format);
-  status = TrioScan(file, 0, TrioInStreamFile, format, args, NULL);
-  va_end(args);
+  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(FILE *file,
-	     TRIO_CONST char *format,
-	     va_list args)
+trio_vfscanf
+TRIO_ARGS3((file, format, args),
+	   FILE *file,
+	   TRIO_CONST char *format,
+	   va_list args)
 {
   assert(VALID(file));
   assert(VALID(format));
   
-  return TrioScan(file, 0, TrioInStreamFile, format, args, NULL);
+  return TrioScan((trio_pointer_t)file, 0,
+		  TrioInStreamFile,
+		  format, &args, NULL);
 }
 
 TRIO_PUBLIC int
-trio_fscanfv(FILE *file,
-	     TRIO_CONST char *format,
-	     void **args)
+trio_fscanfv
+TRIO_ARGS3((file, format, args),
+	   FILE *file,
+	   TRIO_CONST char *format,
+	   trio_pointer_t *args)
 {
-  va_list dummy;
-  
   assert(VALID(file));
   assert(VALID(format));
   
-  return TrioScan(file, 0, TrioInStreamFile, format, dummy, args);
+  return TrioScan((trio_pointer_t)file, 0,
+		  TrioInStreamFile,
+		  format, NULL, args);
 }
 
 /*************************************************************************
  * dscanf
  */
 TRIO_PUBLIC int
-trio_dscanf(int fd,
+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));
   
-  va_start(args, format);
-  status = TrioScan(&fd, 0, TrioInStreamFileDescriptor, format, args, NULL);
-  va_end(args);
+  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(int fd,
-	     TRIO_CONST char *format,
-	     va_list args)
+trio_vdscanf
+TRIO_ARGS3((fd, format, args),
+	   int fd,
+	   TRIO_CONST char *format,
+	   va_list args)
 {
   assert(VALID(format));
   
-  return TrioScan(&fd, 0, TrioInStreamFileDescriptor, format, args, NULL);
+  return TrioScan((trio_pointer_t)&fd, 0,
+		  TrioInStreamFileDescriptor,
+		  format, &args, NULL);
 }
 
 TRIO_PUBLIC int
-trio_dscanfv(int fd,
-             TRIO_CONST char *format,
-             void **args)
+trio_dscanfv
+TRIO_ARGS3((fd, format, args),
+	   int fd,
+	   TRIO_CONST char *format,
+	   trio_pointer_t *args)
 {
-  va_list dummy;
-  
   assert(VALID(format));
   
-  return TrioScan(&fd, 0, TrioInStreamFileDescriptor, format, dummy, args);
+  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_CONST char *buffer,
+trio_sscanf
+TRIO_VARGS3((buffer, format, va_alist),
+	    TRIO_CONST char *buffer,
 	    TRIO_CONST char *format,
-	    ...)
+	    TRIO_VA_DECL)
 {
   int status;
   va_list args;
@@ -5760,34 +6687,74 @@
   assert(VALID(buffer));
   assert(VALID(format));
   
-  va_start(args, format);
-  status = TrioScan(&buffer, 0, TrioInStreamString, format, args, NULL);
-  va_end(args);
+  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_CONST char *buffer,
-	     TRIO_CONST char *format,
-	     va_list args)
+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(&buffer, 0, TrioInStreamString, format, args, NULL);
+  return TrioScan((trio_pointer_t)&buffer, 0,
+		  TrioInStreamString,
+		  format, &args, NULL);
 }
 
 TRIO_PUBLIC int
-trio_sscanfv(TRIO_CONST char *buffer,
-	     TRIO_CONST char *format,
-	     void **args)
+trio_sscanfv
+TRIO_ARGS3((buffer, format, args),
+	   TRIO_CONST char *buffer,
+	   TRIO_CONST char *format,
+	   trio_pointer_t *args)
 {
-  va_list dummy;
-  
   assert(VALID(buffer));
   assert(VALID(format));
   
-  return TrioScan(&buffer, 0, TrioInStreamString, format, dummy, args);
+  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.h b/trio.h
index 5a38f4a..770c6a6 100644
--- a/trio.h
+++ b/trio.h
@@ -23,8 +23,14 @@
 #define TRIO_TRIO_H
 
 #include <stdio.h>
-#include <stdarg.h>
 #include <stdlib.h>
+#if defined(TRIO_COMPILER_ANCIENT)
+# include <varargs.h>
+#else
+# include <stdarg.h>
+#endif
+
+#if !defined(WITHOUT_TRIO)
 
 /*
  * Use autoconf defines if present. Packages using trio must define
@@ -34,22 +40,12 @@
 # include <config.h>
 #endif
 
-#if !defined(WITHOUT_TRIO)
+#include "triodef.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-/* make utility and C++ compiler in Windows NT fails to find this symbol */ 
-#if defined(WIN32) && !defined(isascii)
-# define isascii ((unsigned)(x) < 0x80)
-#endif
-
-/* Error macros */
-#define TRIO_ERROR_CODE(x) ((-(x)) & 0x00FF)
-#define TRIO_ERROR_POSITION(x) ((-(x)) >> 8)
-#define TRIO_ERROR_NAME(x) trio_strerror(x)
-
 /*
  * Error codes.
  *
@@ -63,72 +59,95 @@
   TRIO_EGAP     = 5,
   TRIO_ENOMEM   = 6,
   TRIO_ERANGE   = 7,
-  TRIO_ERRNO    = 8
+  TRIO_ERRNO    = 8,
+  TRIO_ECUSTOM  = 9
 };
 
-const char *trio_strerror(int);
+/* 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(const char *format, ...);
-int trio_vprintf(const char *format, va_list args);
-int trio_printfv(const char *format, void **args);
+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(FILE *file, const char *format, ...);
-int trio_vfprintf(FILE *file, const char *format, va_list args);
-int trio_fprintfv(FILE *file, 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(int fd, const char *format, ...);
-int trio_vdprintf(int fd, const char *format, va_list args);
-int trio_dprintfv(int fd, 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));
 
-/* trio_sprintf(target, format, ...)
- * trio_snprintf(target, maxsize, format, ...)
- *
- *   Build 'target' according to 'format' and succesive
- *   arguments. This is equal to the sprintf() and
- *   snprintf() functions.
- */
-int trio_sprintf(char *buffer, const char *format, ...);
-int trio_vsprintf(char *buffer, const char *format, va_list args);
-int trio_sprintfv(char *buffer, 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_snprintf(char *buffer, size_t max, const char *format, ...);
-int trio_vsnprintf(char *buffer, size_t bufferSize, const char *format,
-		   va_list args);
-int trio_snprintfv(char *buffer, size_t bufferSize, 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_snprintfcat(char *buffer, size_t max, const char *format, ...);
-int trio_vsnprintfcat(char *buffer, size_t bufferSize, const char *format,
-                      va_list 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));
 
-char *trio_aprintf(const char *format, ...);
-char *trio_vaprintf(const char *format, va_list 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));
 
-int trio_asprintf(char **ret, const char *format, ...);
-int trio_vasprintf(char **ret, 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(const char *format, ...);
-int trio_vscanf(const char *format, va_list args);
-int trio_scanfv(const char *format, void **args);
+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(FILE *file, const char *format, ...);
-int trio_vfscanf(FILE *file, const char *format, va_list args);
-int trio_fscanfv(FILE *file, 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(int fd, const char *format, ...);
-int trio_vdscanf(int fd, const char *format, va_list args);
-int trio_dscanfv(int fd, 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_sscanf(const char *buffer, const char *format, ...);
-int trio_vsscanf(const char *buffer, const char *format, va_list args);
-int trio_sscanfv(const char *buffer, 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
diff --git a/triodef.h b/triodef.h
index 3e12cc4..e9b62e5 100644
--- a/triodef.h
+++ b/triodef.h
@@ -34,8 +34,12 @@
 # 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(unix) || defined(__unix) || defined(__unix__)
@@ -61,9 +65,10 @@
 # define TRIO_PLATFORM_MPEIX
 #endif
 
-#if defined(__STDC__)
-# define TRIO_COMPILER_SUPPORTS_C90
+#if defined(__STDC__) || defined(TRIO_COMPILER_MSVC)
+# define TRIO_COMPILER_SUPPORTS_C89
 # if defined(__STDC_VERSION__)
+#  define TRIO_COMPILER_SUPPORTS_C90
 #  if (__STDC_VERSION__ >= 199409L)
 #   define TRIO_COMPILER_SUPPORTS_C94
 #  endif
@@ -84,6 +89,9 @@
 # if (_XOPEN_VERSION >= 500)
 #  define TRIO_COMPILER_SUPPORTS_UNIX98
 # endif
+# if (_XOPEN_VERSION >= 600)
+#  define TRIO_COMPILER_SUPPORTS_UNIX01
+# endif
 #endif
 
 /*************************************************************************
@@ -97,22 +105,64 @@
 # define TRIO_PRIVATE static
 #endif
 
-#if defined(TRIO_COMPILER_SUPPORTS_C90) || defined(__cplusplus)
-# define TRIO_CONST const
-# define TRIO_VOLATILE volatile
-# define TRIO_POINTER void *
-# define TRIO_PROTO(x) x
-#else
+#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_POINTER char *
+# 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
diff --git a/trionan.c b/trionan.c
index 6f67c5b..5d63ad7 100644
--- a/trionan.c
+++ b/trionan.c
@@ -29,40 +29,13 @@
  *   2. Use IEEE 754 bit-patterns if possible.
  *   3. Use platform-specific techniques.
  *
- * This program has been tested on the following platforms (in
- * alphabetic order)
- *
- *   OS              CPU          Compiler
- * -------------------------------------------------
- *   AIX 4.1.4       PowerPC      gcc
- *   Darwin 1.3.7    PowerPC      gcc
- *   FreeBSD 2.2     x86          gcc
- *   FreeBSD 3.3     x86          gcc
- *   FreeBSD 4.3     x86          gcc
- *   FreeBSD 4.3     Alpha        gcc
- *   HP-UX 10.20     PA-RISC      gcc
- *   HP-UX 10.20     PA-RISC      HP C++
- *   IRIX 6.5        MIPS         MIPSpro C
- *   Linux 2.2       x86          gcc
- *   Linux 2.2       Alpha        gcc
- *   Linux 2.4       IA64         gcc
- *   Linux 2.4       StrongARM    gcc
- *   NetBSD 1.4      x86          gcc
- *   NetBSD 1.4      StrongARM    gcc
- *   NetBSD 1.5      Alpha        gcc
- *   OpenVMS 7.1     Alpha        DEC C 6.0
- *   RISC OS 4       StrongARM    Norcroft C
- *   Solaris 2.5.1   x86          gcc
- *   Solaris 2.5.1   Sparc        gcc
- *   Solaris 2.6     Sparc        WorkShop 4.2
- *   Solaris 8       Sparc        Forte C 6
- *   Tru64 4.0D      Alpha        gcc
- *   Tru64 5.1       Alpha        gcc
- *   WinNT           x86          MSVC 5.0 & 6.0
- *
  ************************************************************************/
 
-static const char rcsid[] = "@(#)$Id$";
+/*
+ * TODO:
+ *  o Put all the magic into trio_fpclassify_and_signbit(), and use this from
+ *    trio_isnan() etc.
+ */
 
 /*************************************************************************
  * Include files
@@ -102,7 +75,9 @@
 #  if defined(TRIO_PLATFORM_VMS)
 #   error "Must be compiled with option /IEEE_MODE=UNDERFLOW_TO_ZERO/FLOAT=IEEE"
 #  else
-#   error "Must be compiled with option -ieee"
+#   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"
@@ -128,9 +103,11 @@
 
 
 /*************************************************************************
- * Data
+ * Constants
  */
 
+static TRIO_CONST char rcsid[] = "@(#)$Id$";
+
 #if defined(USE_IEEE_754)
 
 /*
@@ -187,7 +164,9 @@
  * trio_make_double
  */
 TRIO_PRIVATE double
-trio_make_double(TRIO_CONST unsigned char *values)
+trio_make_double
+TRIO_ARGS1((values),
+	   TRIO_CONST unsigned char *values)
 {
   TRIO_VOLATILE double result;
   int i;
@@ -202,8 +181,10 @@
  * trio_is_special_quantity
  */
 TRIO_PRIVATE int
-trio_is_special_quantity(double number,
-			 int *has_mantissa)
+trio_is_special_quantity
+TRIO_ARGS2((number, has_mantissa),
+	   double number,
+	   int *has_mantissa)
 {
   unsigned int i;
   unsigned char current;
@@ -224,7 +205,9 @@
  * trio_is_negative
  */
 TRIO_PRIVATE int
-trio_is_negative(double number)
+trio_is_negative
+TRIO_ARGS1((number),
+	   double number)
 {
   unsigned int i;
   int is_negative = TRIO_FALSE;
@@ -236,22 +219,33 @@
   return is_negative;
 }
 
-TRIO_PUBLIC double
-trio_nzero(void)
-{
-  return trio_make_double(ieee_754_negzero_array);
-}
-
 #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(void)
+trio_pinf(TRIO_NOARGS)
 {
   /* Cache the result */
   static double result = 0.0;
@@ -295,7 +289,7 @@
    @return Floating-point value of negative infinity.
 */
 TRIO_PUBLIC double
-trio_ninf(void)
+trio_ninf(TRIO_NOARGS)
 {
   static double result = 0.0;
 
@@ -316,7 +310,7 @@
    @return Floating-point representation of NaN.
 */
 TRIO_PUBLIC double
-trio_nan(void)
+trio_nan(TRIO_NOARGS)
 {
   /* Cache the result */
   static double result = 0.0;
@@ -364,9 +358,12 @@
    @return Boolean value indicating whether or not the number is a NaN.
 */
 TRIO_PUBLIC int
-trio_isnan(TRIO_VOLATILE double number)
+trio_isnan
+TRIO_ARGS1((number),
+	   double number)
 {
-#if defined(isnan) || defined(TRIO_COMPILER_SUPPORTS_UNIX95)
+#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
@@ -407,7 +404,7 @@
   status = (/*
 	     * NaN is the only number which does not compare to itself
 	     */
-	    (number != number) ||
+	    ((TRIO_VOLATILE double)number != (TRIO_VOLATILE double)number) ||
 	    /*
 	     * Fallback solution if NaN compares to NaN
 	     */
@@ -431,7 +428,9 @@
    @return 1 if positive infinity, -1 if negative infinity, 0 otherwise.
 */
 TRIO_PUBLIC int
-trio_isinf(TRIO_VOLATILE double number)
+trio_isinf
+TRIO_ARGS1((number),
+	   double number)
 {
 #if defined(TRIO_COMPILER_DECC)
   /*
@@ -441,12 +440,14 @@
   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);
+  return isinf(number)
+    ? ((number > 0.0) ? 1 : -1)
+    : 0;
   
 #elif defined(TRIO_COMPILER_MSVC)
   /*
@@ -503,9 +504,11 @@
    @return Boolean value indicating whether or not the number is a finite.
 */
 TRIO_PUBLIC int
-trio_isfinite(TRIO_VOLATILE double number)
+trio_isfinite
+TRIO_ARGS1((number),
+	   double number)
 {
-#if defined(isfinite)
+#if defined(TRIO_COMPILER_SUPPORTS_C99) && defined(isfinite)
   /*
    * C99 defines isfinite() as a macro.
    */
@@ -538,9 +541,11 @@
 /*
  * The sign of NaN is always false
  */
-TRIO_PRIVATE int
-trio_fpclass(TRIO_VOLATILE double number,
-	     int *is_negative)
+TRIO_PUBLIC int
+trio_fpclassify_and_signbit
+TRIO_ARGS2((number, is_negative),
+	   double number,
+	   int *is_negative)
 {
 #if defined(fpclassify) && defined(signbit)
   /*
@@ -637,7 +642,46 @@
     *is_negative = (number < 0.0);
     return TRIO_FP_NORMAL;
   }
-  
+
+#elif defined(FP_PLUS_NORM) || defined(__hpux)
+
+  /*
+   * 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.
+   */
+  switch (fpclassify(number)) {
+  case FP_QNAN:
+  case FP_SNAN:
+    *is_negative = TRIO_FALSE;
+    return TRIO_FP_NAN;
+  case FP_PLUS_INF:
+    *is_negative = TRIO_FALSE;
+    return TRIO_FP_INFINITE;
+  case FP_MINUS_INF:
+    *is_negative = TRIO_TRUE;
+    return TRIO_FP_INFINITE;
+  case FP_PLUS_DENORM:
+    *is_negative = TRIO_FALSE;
+    return TRIO_FP_SUBNORMAL;
+  case FP_MINUS_DENORM:
+    *is_negative = TRIO_TRUE;
+    return TRIO_FP_SUBNORMAL;
+  case FP_PLUS_ZERO:
+    *is_negative = TRIO_FALSE;
+    return TRIO_FP_ZERO;
+  case FP_MINUS_ZERO:
+    *is_negative = TRIO_TRUE;
+    return TRIO_FP_ZERO;
+  case FP_PLUS_NORM:
+    *is_negative = TRIO_FALSE;
+    return TRIO_FP_NORMAL;
+  case FP_MINUS_NORM:
+    *is_negative = TRIO_TRUE;
+    return TRIO_FP_NORMAL;
+  default:
+    assert(0);
+  }
+
 #else
   /*
    * Fallback solution.
@@ -687,11 +731,13 @@
    sign bit set (i.e. is negative).
 */
 TRIO_PUBLIC int
-trio_signbit(TRIO_VOLATILE double number)
+trio_signbit
+TRIO_ARGS1((number),
+	   double number)
 {
   int is_negative;
   
-  (void)trio_fpclass(number, &is_negative);
+  (void)trio_fpclassify_and_signbit(number, &is_negative);
   return is_negative;
 }
 
@@ -702,11 +748,13 @@
    @return Enumerable value indicating the class of @p number
 */
 TRIO_PUBLIC int
-trio_fpclassify(TRIO_VOLATILE double number)
+trio_fpclassify
+TRIO_ARGS1((number),
+	   double number)
 {
   int dummy;
   
-  return trio_fpclass(number, &dummy);
+  return trio_fpclassify_and_signbit(number, &dummy);
 }
 
 
@@ -723,7 +771,10 @@
 #if defined(STANDALONE)
 # include <stdio.h>
 
-static const char *getClassification(int type)
+static TRIO_CONST char *
+getClassification
+TRIO_ARGS1((type)
+	   int type)
 {
   switch (type) {
   case TRIO_FP_INFINITE:
@@ -741,7 +792,11 @@
   }
 }
 
-static void print_class(const char *prefix, double number)
+static void
+print_class
+TRIO_ARGS2((prefix, number)
+	   TRIO_CONST char *prefix,
+	   double number)
 {
   printf("%-6s: %s %-15s %g\n",
 	 prefix,
@@ -750,13 +805,13 @@
 	 number);
 }
 
-int main(void)
+int main(TRIO_NOARGS)
 {
   double my_nan;
   double my_pinf;
   double my_ninf;
 # if defined(TRIO_PLATFORM_UNIX)
-  void (*signal_handler)(int);
+  void (*signal_handler) TRIO_PROTO((int));
 # endif
 
   my_nan = trio_nan();
diff --git a/trionan.h b/trionan.h
index ab2102d..bed0c12 100644
--- a/trionan.h
+++ b/trionan.h
@@ -35,39 +35,44 @@
 /*
  * Return NaN (Not-a-Number).
  */
-TRIO_PUBLIC double trio_nan(void);
+TRIO_PUBLIC double trio_nan TRIO_PROTO((void));
 
 /*
  * Return positive infinity.
  */
-TRIO_PUBLIC double trio_pinf(void);
+TRIO_PUBLIC double trio_pinf TRIO_PROTO((void));
 
 /*
  * Return negative infinity.
  */
-TRIO_PUBLIC double trio_ninf(void);
+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(double number);
+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(double number);
+TRIO_PUBLIC int trio_isinf TRIO_PROTO((double number));
 
 /*
  * If number is finite return non-zero, otherwise return zero.
  */
-TRIO_PUBLIC int trio_isfinite(double number);
+TRIO_PUBLIC int trio_isfinite TRIO_PROTO((double number));
 
-TRIO_PUBLIC int trio_signbit(double number);
+TRIO_PUBLIC int trio_signbit TRIO_PROTO((double number));
 
-TRIO_PUBLIC int trio_fpclassify(double number);
+TRIO_PUBLIC int trio_fpclassify TRIO_PROTO((double number));
 
-TRIO_PUBLIC double trio_nzero(void);
+TRIO_PUBLIC int trio_fpclassify_and_signbit TRIO_PROTO((double number, int *is_negative));
 
 #ifdef __cplusplus
 }
diff --git a/triop.h b/triop.h
index ead673a..8462c56 100644
--- a/triop.h
+++ b/triop.h
@@ -26,8 +26,14 @@
 #ifndef TRIO_TRIOP_H
 #define TRIO_TRIOP_H
 
+#include "triodef.h"
+
 #include <stdlib.h>
-#include <stdarg.h>
+#if defined(TRIO_COMPILER_ANCIENT)
+# include <varargs.h>
+#else
+# include <stdarg.h>
+#endif
 
 #ifdef __cplusplus
 extern "C" {
@@ -71,70 +77,71 @@
 # define TRIO_FREE(x) free(x)
 #endif
 
+
 /*************************************************************************
  * User-defined specifiers
  */
 
-typedef int (*trio_callback_t)(void *);
+typedef int (*trio_callback_t) TRIO_PROTO((trio_pointer_t));
 
-void *trio_register(trio_callback_t callback, const char *name);
-void trio_unregister(void *handle);
+trio_pointer_t trio_register TRIO_PROTO((trio_callback_t callback, const char *name));
+void trio_unregister TRIO_PROTO((trio_pointer_t handle));
 
-const char *trio_get_format(void *ref);
-void *trio_get_argument(void *ref);
+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(void *ref);
-void trio_set_width(void *ref, int width);
-int  trio_get_precision(void *ref);
-void trio_set_precision(void *ref, int precision);
-int  trio_get_base(void *ref);
-void trio_set_base(void *ref, int base);
-int  trio_get_padding(void *ref);
-void trio_set_padding(void *ref, int is_padding);
-int  trio_get_short(void *ref); /* h */
-void trio_set_shortshort(void *ref, int is_shortshort);
-int  trio_get_shortshort(void *ref); /* hh */
-void trio_set_short(void *ref, int is_short);
-int  trio_get_long(void *ref); /* l */
-void trio_set_long(void *ref, int is_long);
-int  trio_get_longlong(void *ref); /* ll */
-void trio_set_longlong(void *ref, int is_longlong);
-int  trio_get_longdouble(void *ref); /* L */
-void trio_set_longdouble(void *ref, int is_longdouble);
-int  trio_get_alternative(void *ref); /* # */
-void trio_set_alternative(void *ref, int is_alternative);
-int  trio_get_alignment(void *ref); /* - */
-void trio_set_alignment(void *ref, int is_leftaligned);
-int  trio_get_spacing(void *ref); /* (space) */
-void trio_set_spacing(void *ref, int is_space);
-int  trio_get_sign(void *ref); /* + */
-void trio_set_sign(void *ref, int is_showsign);
-int  trio_get_quote(void *ref); /* ' */
-void trio_set_quote(void *ref, int is_quote);
-int  trio_get_upper(void *ref);
-void trio_set_upper(void *ref, int is_upper);
+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(void *ref); /* j */
-void trio_set_largest(void *ref, int is_largest);
-int  trio_get_ptrdiff(void *ref); /* t */
-void trio_set_ptrdiff(void *ref, int is_ptrdiff);
-int  trio_get_size(void *ref); /* z / Z */
-void trio_set_size(void *ref, int is_size);
+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(void *ref, const char *format, ...);
-int trio_vprint_ref(void *ref, const char *format, va_list args);
-int trio_printv_ref(void *ref, const char *format, void **args);
+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(void *ref, int number);
-void trio_print_uint(void *ref, unsigned int number);
-/*  void trio_print_long(void *ref, long number); */
-/*  void trio_print_ulong(void *ref, unsigned long number); */
-void trio_print_double(void *ref, double number);
-void trio_print_string(void *ref, char *string);
-void trio_print_pointer(void *ref, void *pointer);
+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" */
diff --git a/triostr.c b/triostr.c
index 760be55..43a30da 100644
--- a/triostr.c
+++ b/triostr.c
@@ -15,8 +15,6 @@
  *
  ************************************************************************/
 
-static const char rcsid[] = "@(#)$Id$";
-
 /*************************************************************************
  * Include files
  */
@@ -26,21 +24,33 @@
 #include <string.h>
 #include <ctype.h>
 #include <math.h>
+#include "triodef.h"
 #include "triostr.h"
 
 /*************************************************************************
  * Definitions
  */
 
-#ifndef NULL
+#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
-#define NIL ((char)0)
-#ifndef FALSE
+#if !defined(NIL)
+# define NIL ((char)0)
+#endif
+#if !defined(FALSE)
 # define FALSE (1 == 0)
 # define TRUE (! FALSE)
 #endif
-#define BOOLEAN_T int
+#if !defined(BOOLEAN_T)
+# define BOOLEAN_T int
+#endif
 
 #if defined(TRIO_COMPILER_SUPPORTS_C99)
 # define USE_STRTOD
@@ -74,6 +84,14 @@
 };
 
 /*************************************************************************
+ * Constants
+ */
+
+#if !defined(TRIO_MINIMAL)
+static TRIO_CONST char rcsid[] = "@(#)$Id$";
+#endif
+
+/*************************************************************************
  * Static String Functions
  */
 
@@ -90,8 +108,10 @@
    @param size Size of new string.
    @return Pointer to string, or NULL if allocation failed.
 */
-TRIO_PUBLIC TRIO_INLINE char *
-trio_create(size_t size)
+TRIO_STRING_PUBLIC char *
+trio_create
+TRIO_ARGS1((size),
+	   size_t size)
 {
   return (char *)TRIO_MALLOC(size);
 }
@@ -102,8 +122,10 @@
 
    @param string String to be freed.
 */
-TRIO_PUBLIC TRIO_INLINE void
-trio_destroy(char *string)
+TRIO_STRING_PUBLIC void
+trio_destroy
+TRIO_ARGS1((string),
+	   char *string)
 {
   if (string)
     {
@@ -118,18 +140,171 @@
    @param string String to measure.
    @return Number of characters in @string.
 */
-TRIO_PUBLIC TRIO_INLINE size_t
-trio_length(const char *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_PRIVATE char *
-TrioDuplicateMax(const char *source, size_t size)
+TRIO_STRING_PRIVATE char *
+TrioDuplicateMax
+TRIO_ARGS2((source, size),
+	   TRIO_CONST char *source,
+	   size_t size)
 {
   char *target;
 
@@ -147,137 +322,6 @@
 
 
 /**
-   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_PUBLIC int
-trio_append(char *target,
-	    const char *source)
-{
-  assert(target);
-  assert(source);
-  
-  return (strcat(target, source) != NULL);
-}
-
-
-/**
-   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_PUBLIC int
-trio_append_max(char *target,
-		size_t max,
-		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;
-}
-
-
-/**
-   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_PUBLIC TRIO_INLINE int
-trio_contains(const char *string,
-	      const char *substring)
-{
-  assert(string);
-  assert(substring);
-  
-  return (0 != strstr(string, substring));
-}
-
-
-/**
-   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_PUBLIC int
-trio_copy(char *target,
-	  const char *source)
-{
-  assert(target);
-  assert(source);
-
-  (void)strcpy(target, source);
-  return TRUE;
-}
-
-
-/**
-   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_PUBLIC int
-trio_copy_max(char *target,
-	      size_t max,
-	      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;
-}
-
-
-/**
    Duplicate @p source.
    
    @param source Source string.
@@ -285,13 +329,16 @@
    
    @post @p target will be zero terminated.
 */
-TRIO_PUBLIC char *
-trio_duplicate(const char *source)
+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.
    
@@ -301,9 +348,10 @@
    
    @post @p target will be zero terminated.
 */
-TRIO_PUBLIC char *
-trio_duplicate_max(const char *source,
-		   size_t max)
+TRIO_STRING_PUBLIC char *
+trio_duplicate_max TRIO_ARGS2((source, max),
+			      TRIO_CONST char *source,
+			      size_t max)
 {
   size_t length;
 
@@ -317,6 +365,7 @@
     }
   return TrioDuplicateMax(source, length);
 }
+#endif /* !defined(TRIO_MINIMAL) */
 
 
 /**
@@ -328,9 +377,11 @@
    
    Case-insensitive comparison.
 */
-TRIO_PUBLIC int
-trio_equal(const char *first,
-	   const char *second)
+TRIO_STRING_PUBLIC int
+trio_equal
+TRIO_ARGS2((first, second),
+	   TRIO_CONST char *first,
+	   TRIO_CONST char *second)
 {
   assert(first);
   assert(second);
@@ -365,9 +416,11 @@
    
    Case-sensitive comparison.
 */
-TRIO_PUBLIC int
-trio_equal_case(const char *first,
-		const char *second)
+TRIO_STRING_PUBLIC int
+trio_equal_case
+TRIO_ARGS2((first, second),
+	   TRIO_CONST char *first,
+	   TRIO_CONST char *second)
 {
   assert(first);
   assert(second);
@@ -380,6 +433,7 @@
 }
 
 
+#if !defined(TRIO_MINIMAL)
 /**
    Compare if two strings up until the first @p max characters are equal.
    
@@ -390,10 +444,12 @@
    
    Case-sensitive comparison.
 */
-TRIO_PUBLIC int
-trio_equal_case_max(const char *first,
-		    size_t max,
-		    const char *second)
+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);
@@ -404,6 +460,7 @@
     }
   return FALSE;
 }
+#endif /* !defined(TRIO_MINIMAL) */
 
 
 /**
@@ -415,9 +472,11 @@
 
    Collating characters are considered equal.
 */
-TRIO_PUBLIC int
-trio_equal_locale(const char *first,
-		  const char *second)
+TRIO_STRING_PUBLIC int
+trio_equal_locale
+TRIO_ARGS2((first, second),
+	   TRIO_CONST char *first,
+	   TRIO_CONST char *second)
 {
   assert(first);
   assert(second);
@@ -440,10 +499,12 @@
    
    Case-insensitive comparison.
 */
-TRIO_PUBLIC int
-trio_equal_max(const char *first,
-	       size_t max,
-	       const char *second)
+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);
@@ -478,8 +539,10 @@
    @param error_number Error number.
    @return Textual description of @p error_number.
 */
-TRIO_PUBLIC const char *
-trio_error(int 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);
@@ -489,6 +552,7 @@
 }
 
 
+#if !defined(TRIO_MINIMAL)
 /**
    Format the date/time according to @p format.
 
@@ -501,11 +565,13 @@
    The formatting string accepts the same specifiers as the standard C
    function strftime.
 */
-TRIO_PUBLIC size_t
-trio_format_date_max(char *target,
-		     size_t max,
-		     const char *format,
-		     const struct tm *datetime)
+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);
@@ -514,8 +580,10 @@
   
   return strftime(target, max, format, datetime);
 }
+#endif /* !defined(TRIO_MINIMAL) */
 
 
+#if !defined(TRIO_MINIMAL)
 /**
    Calculate a hash value for a string.
 
@@ -526,9 +594,11 @@
    @p type can be one of the following
    @li @c TRIO_HASH_PLAIN Plain hash function.
 */
-TRIO_PUBLIC unsigned long
-trio_hash(const char *string,
-	  int type)
+TRIO_STRING_PUBLIC unsigned long
+trio_hash
+TRIO_ARGS2((string, type),
+	   TRIO_CONST char *string,
+	   int type)
 {
   unsigned long value = 0L;
   char ch;
@@ -550,8 +620,10 @@
     }
   return value;
 }
+#endif /* !defined(TRIO_MINIMAL) */
 
 
+#if !defined(TRIO_MINIMAL)
 /**
    Find first occurrence of a character in a string.
 
@@ -559,16 +631,20 @@
    @param character Character to be found.
    @param A pointer to the found character, or NULL if character was not found.
  */
-TRIO_PUBLIC TRIO_INLINE char *
-trio_index(const char *string,
-	   char character)
+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.
 
@@ -576,31 +652,39 @@
    @param character Character to be found.
    @param A pointer to the found character, or NULL if character was not found.
  */
-TRIO_PUBLIC TRIO_INLINE char *
-trio_index_last(const char *string,
-		char character)
+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_PUBLIC TRIO_INLINE int
-trio_lower(char *target)
+TRIO_STRING_PUBLIC int
+trio_lower
+TRIO_ARGS1((target),
+	   char *target)
 {
   assert(target);
 
   return trio_span_function(target, target, tolower);
 }
+#endif /* !defined(TRIO_MINIMAL) */
 
 
+#if !defined(TRIO_MINIMAL)
 /**
    Compare two strings using wildcards.
 
@@ -614,9 +698,11 @@
    @li @c * Match any number of characters.
    @li @c ? Match a single character.
 */
-TRIO_PUBLIC int
-trio_match(const char *string,
-	   const char *pattern)
+TRIO_STRING_PUBLIC int
+trio_match
+TRIO_ARGS2((string, pattern),
+	   TRIO_CONST char *string,
+	   TRIO_CONST char *pattern)
 {
   assert(string);
   assert(pattern);
@@ -648,8 +734,10 @@
   
   return FALSE;
 }
+#endif /* !defined(TRIO_MINIMAL) */
 
 
+#if !defined(TRIO_MINIMAL)
 /**
    Compare two strings using wildcards.
 
@@ -663,9 +751,11 @@
    @li @c * Match any number of characters.
    @li @c ? Match a single character.
 */
-TRIO_PUBLIC int
-trio_match_case(const char *string,
-		const char *pattern)
+TRIO_STRING_PUBLIC int
+trio_match_case
+TRIO_ARGS2((string, pattern),
+	   TRIO_CONST char *string,
+	   TRIO_CONST char *pattern)
 {
   assert(string);
   assert(pattern);
@@ -697,8 +787,10 @@
   
   return FALSE;
 }
+#endif /* !defined(TRIO_MINIMAL) */
 
 
+#if !defined(TRIO_MINIMAL)
 /**
    Execute a function on each character in string.
 
@@ -707,10 +799,12 @@
    @param Function Function to be executed.
    @return Number of processed characters.
 */
-TRIO_PUBLIC size_t
-trio_span_function(char *target,
-		   const char *source,
-		   int (*Function)(int))
+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;
 
@@ -725,8 +819,10 @@
     }
   return count;
 }
+#endif /* !defined(TRIO_MINIMAL) */
 
 
+#if !defined(TRIO_MINIMAL)
 /**
    Search for a substring in a string.
 
@@ -735,17 +831,21 @@
    @return Pointer to first occurrence of @p substring in @p string, or NULL
    if no match was found.
 */
-TRIO_PUBLIC TRIO_INLINE char *
-trio_substring(const char *string,
-	       const char *substring)
+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.
 
@@ -755,10 +855,12 @@
    @return Pointer to first occurrence of @p substring in @p string, or NULL
    if no match was found.
 */
-TRIO_PUBLIC char *
-trio_substring_max(const char *string,
-		   size_t max,
-		   const char *substring)
+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;
@@ -781,8 +883,10 @@
     }
   return result;
 }
+#endif /* !defined(TRIO_MINIMAL) */
 
 
+#if !defined(TRIO_MINIMAL)
 /**
    Tokenize string.
 
@@ -792,13 +896,17 @@
 
    @warning @p string will be destroyed.
 */
-TRIO_PUBLIC TRIO_INLINE char *
-trio_tokenize(char *string, const char *delimiters)
+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) */
 
 
 /**
@@ -823,29 +931,32 @@
    @endverbatim
 */
 /* FIXME: Add EBNF for hex-floats */
-TRIO_PUBLIC double
-trio_to_double(const char *source,
-	       const char **endp)
+TRIO_STRING_PUBLIC trio_long_double_t
+trio_to_long_double
+TRIO_ARGS2((source, endp),
+	   TRIO_CONST char *source,
+	   char **endp)
 {
-#if defined(USE_STRTOD)
-  return strtod(source, (char **)endp);
+#if defined(USE_STRTOLD)
+  return strtold(source, endp);
 #else
-  /* Preliminary code */
   int isNegative = FALSE;
   int isExponentNegative = FALSE;
-  unsigned long integer = 0;
-  unsigned long fraction = 0;
-  unsigned long fracdiv = 1;
+  trio_long_double_t integer = 0.0;
+  trio_long_double_t fraction = 0.0;
   unsigned long exponent = 0;
-  double value = 0.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 *= 16;
+	  integer *= base;
 	  integer += (isdigit((int)*source)
 		      ? (*source - '0')
 		      : 10 + (toupper((int)*source) - 'A'));
@@ -856,11 +967,10 @@
 	  source++;
 	  while (isxdigit((int)*source))
 	    {
-	      fraction *= 16;
-	      fraction += (isdigit((int)*source)
-			   ? (*source - '0')
-			   : 10 + (toupper((int)*source) - 'A'));
-	      fracdiv *= 16;
+	      fracdiv /= base;
+	      fraction += fracdiv * (isdigit((int)*source)
+				     ? (*source - '0')
+				     : 10 + (toupper((int)*source) - 'A'));
 	      source++;
 	    }
 	  if ((*source == 'p') || (*source == 'P'))
@@ -873,7 +983,7 @@
 		}
 	      while (isdigit((int)*source))
 		{
-		  exponent *= 10;
+		  exponent *= (int)base;
 		  exponent += (*source - '0');
 		  source++;
 		}
@@ -882,6 +992,7 @@
     }
   else /* Then try normal decimal floats */
     {
+      base = 10.0;
       isNegative = (*source == '-');
       /* Skip sign */
       if ((*source == '+') || (*source == '-'))
@@ -890,7 +1001,7 @@
       /* Integer part */
       while (isdigit((int)*source))
 	{
-	  integer *= 10;
+	  integer *= base;
 	  integer += (*source - '0');
 	  source++;
 	}
@@ -900,9 +1011,8 @@
 	  source++; /* skip decimal point */
 	  while (isdigit((int)*source))
 	    {
-	      fraction *= 10;
-	      fraction += (*source - '0');
-	      fracdiv *= 10;
+	      fracdiv /= base;
+	      fraction += (*source - '0') * fracdiv;
 	      source++;
 	    }
 	}
@@ -920,30 +1030,26 @@
 	    source++;
 	  while (isdigit((int)*source))
 	    {
-	      exponent *= 10;
+	      exponent *= (int)base;
 	      exponent += (*source - '0');
 	      source++;
 	    }
 	}
     }
   
-  value = (double)integer;
-  if (fraction != 0)
-    {
-      value += (double)fraction / (double)fracdiv;
-    }
+  value = integer + fraction;
   if (exponent != 0)
     {
       if (isExponentNegative)
-	value /= pow((double)10, (double)exponent);
+	value /= pow(base, (double)exponent);
       else
-	value *= pow((double)10, (double)exponent);
+	value *= pow(base, (double)exponent);
     }
   if (isNegative)
     value = -value;
 
   if (endp)
-    *endp = source;
+    *endp = (char *)source;
   return value;
 #endif
 }
@@ -956,19 +1062,45 @@
    @param endp Pointer to end of the converted string.
    @return A floating-point number.
 
-   See @ref trio_to_double.
+   See @ref trio_to_long_double.
 */
-TRIO_PUBLIC TRIO_INLINE float
-trio_to_float(const char *source,
-	      const char **endp)
+TRIO_STRING_PUBLIC double
+trio_to_double
+TRIO_ARGS2((source, endp),
+	   TRIO_CONST char *source,
+	   char **endp)
 {
-#if defined(USE_STRTOF)
-  return strtof(source, (char **)endp);
+#if defined(USE_STRTOD)
+  return strtod(source, endp);
 #else
-  return (float)trio_to_double(source, endp);
+  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.
@@ -977,10 +1109,12 @@
    @param endp Pointer to end of converted string.
    @param base Radix number of number.
 */
-TRIO_PUBLIC TRIO_INLINE long
-trio_to_long(const char *string,
-	     char **endp,
-	     int base)
+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));
@@ -989,6 +1123,7 @@
 }
 
 
+#if !defined(TRIO_MINIMAL)
 /**
    Convert string to unsigned integer.
 
@@ -996,31 +1131,38 @@
    @param endp Pointer to end of converted string.
    @param base Radix number of number.
 */
-TRIO_PUBLIC TRIO_INLINE unsigned long
-trio_to_unsigned_long(const char *string,
-		      char **endp,
-		      int base)
+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) */
 
 
+#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_PUBLIC TRIO_INLINE int
-trio_upper(char *target)
+TRIO_STRING_PUBLIC int
+trio_upper
+TRIO_ARGS1((target),
+	   char *target)
 {
   assert(target);
 
   return trio_span_function(target, target, toupper);
 }
+#endif /* !defined(TRIO_MINIMAL) */
 
 
 /** @} End of StaticStrings */
@@ -1040,8 +1182,8 @@
 /*
  * TrioStringAlloc
  */
-TRIO_PRIVATE trio_string_t *
-TrioStringAlloc(void)
+TRIO_STRING_PRIVATE trio_string_t *
+TrioStringAlloc(TRIO_NOARGS)
 {
   trio_string_t *self;
   
@@ -1062,9 +1204,11 @@
  * The size of the string will be increased by 'delta' characters. If
  * 'delta' is zero, the size will be doubled.
  */
-TRIO_PRIVATE BOOLEAN_T
-TrioStringGrow(trio_string_t *self,
-	       size_t delta)
+TRIO_STRING_PRIVATE BOOLEAN_T
+TrioStringGrow
+TRIO_ARGS2((self, delta),
+	   trio_string_t *self,
+	   size_t delta)
 {
   BOOLEAN_T status = FALSE;
   char *new_content;
@@ -1092,9 +1236,11 @@
  * 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_PRIVATE BOOLEAN_T
-TrioStringGrowTo(trio_string_t *self,
-		 size_t length)
+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)
@@ -1103,14 +1249,17 @@
 }
 
 
+#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_PUBLIC trio_string_t *
-trio_string_create(int initial_size)
+TRIO_STRING_PUBLIC trio_string_t *
+trio_string_create
+TRIO_ARGS1((initial_size),
+	   int initial_size)
 {
   trio_string_t *self;
 
@@ -1131,6 +1280,7 @@
     }
   return self;
 }
+#endif /* !defined(TRIO_MINIMAL) */
 
 
 /**
@@ -1138,8 +1288,10 @@
    
    @param self Dynamic string
 */
-TRIO_PUBLIC void
-trio_string_destroy(trio_string_t *self)
+TRIO_STRING_PUBLIC void
+trio_string_destroy
+TRIO_ARGS1((self),
+	   trio_string_t *self)
 {
   assert(self);
   
@@ -1151,6 +1303,7 @@
 }
 
 
+#if !defined(TRIO_MINIMAL)
 /**
    Get a pointer to the content.
    
@@ -1165,8 +1318,11 @@
    number of characters from the ending of the string, starting at the
    terminating zero, is returned.
 */
-TRIO_PUBLIC char *
-trio_string_get(trio_string_t *self, int offset)
+TRIO_STRING_PUBLIC char *
+trio_string_get
+TRIO_ARGS2((self, offset),
+	   trio_string_t *self,
+	   int offset)
 {
   char *result = NULL;
   
@@ -1180,7 +1336,7 @@
 	}
       if (offset >= 0)
 	{
-	  if (offset > self->length)
+	  if (offset > (int)self->length)
 	    {
 	      offset = self->length;
 	    }
@@ -1197,6 +1353,7 @@
     }
   return result;
 }
+#endif /* !defined(TRIO_MINIMAL) */
 
 
 /**
@@ -1208,8 +1365,10 @@
    The content is removed from the dynamic string. This enables destruction
    of the dynamic string without deallocation of the content.
 */
-TRIO_PUBLIC char *
-trio_string_extract(trio_string_t *self)
+TRIO_STRING_PUBLIC char *
+trio_string_extract
+TRIO_ARGS1((self),
+	   trio_string_t *self)
 {
   char *result;
   
@@ -1223,6 +1382,7 @@
 }
 
 
+#if !defined(TRIO_MINIMAL)
 /**
    Set the content of the dynamic string.
    
@@ -1236,22 +1396,27 @@
    This function will make a copy of @p buffer.
    You are responsible for deallocating @p buffer yourself.
 */
-TRIO_PUBLIC void
-trio_xstring_set(trio_string_t *self,
-		 char *buffer)
+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_PUBLIC int
-trio_string_size(trio_string_t *self)
+TRIO_STRING_PUBLIC int
+trio_string_size
+TRIO_ARGS1((self),
+	   trio_string_t *self)
 {
   assert(self);
 
@@ -1262,21 +1427,16 @@
 /*
  * trio_string_terminate
  */
-TRIO_PUBLIC void
-trio_string_terminate(trio_string_t *self)
+TRIO_STRING_PUBLIC void
+trio_string_terminate
+TRIO_ARGS1((self),
+	   trio_string_t *self)
 {
-  char *end;
-  
-  assert(self);
-
-  end = trio_string_get(self, -1);
-  if (end)
-    {
-      *end = NIL;
-    }
+  trio_xstring_append_char(self, 0);
 }
 
 
+#if !defined(TRIO_MINIMAL)
 /**
    Append the second string to the first.
    
@@ -1284,9 +1444,11 @@
    @param other Dynamic string to copy from.
    @return Boolean value indicating success or failure.
 */
-TRIO_PUBLIC int
-trio_string_append(trio_string_t *self,
-		   trio_string_t *other)
+TRIO_STRING_PUBLIC int
+trio_string_append
+TRIO_ARGS2((self, other),
+	   trio_string_t *self,
+	   trio_string_t *other)
 {
   size_t length;
   
@@ -1303,14 +1465,18 @@
  error:
   return FALSE;
 }
+#endif /* !defined(TRIO_MINIMAL) */
 
 
+#if !defined(TRIO_MINIMAL)
 /*
  * trio_xstring_append
  */
-TRIO_PUBLIC int
-trio_xstring_append(trio_string_t *self,
-		    const char *other)
+TRIO_STRING_PUBLIC int
+trio_xstring_append
+TRIO_ARGS2((self, other),
+	   trio_string_t *self,
+	   TRIO_CONST char *other)
 {
   size_t length;
   
@@ -1327,18 +1493,21 @@
  error:
   return FALSE;
 }
+#endif /* !defined(TRIO_MINIMAL) */
 
 
 /*
  * trio_xstring_append_char
  */
-TRIO_PUBLIC int
-trio_xstring_append_char(trio_string_t *self,
-			 char character)
+TRIO_STRING_PUBLIC int
+trio_xstring_append_char
+TRIO_ARGS2((self, character),
+	   trio_string_t *self,
+	   char character)
 {
   assert(self);
 
-  if (self->length >= trio_string_size(self))
+  if ((int)self->length >= trio_string_size(self))
     {
       if (!TrioStringGrow(self, 0))
 	goto error;
@@ -1352,6 +1521,7 @@
 }
 
 
+#if !defined(TRIO_MINIMAL)
 /**
    Search for the first occurrence of second parameter in the first.
    
@@ -1359,37 +1529,47 @@
    @param other Dynamic string to copy from.
    @return Boolean value indicating success or failure.
 */
-TRIO_PUBLIC int
-trio_string_contains(trio_string_t *self,
-		     trio_string_t *other)
+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_PUBLIC int
-trio_xstring_contains(trio_string_t *self,
-		      const char *other)
+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_PUBLIC int
-trio_string_copy(trio_string_t *self,
-		 trio_string_t *other)
+TRIO_STRING_PUBLIC int
+trio_string_copy
+TRIO_ARGS2((self, other),
+	   trio_string_t *self,
+	   trio_string_t *other)
 {
   assert(self);
   assert(other);
@@ -1397,14 +1577,18 @@
   self->length = 0;
   return trio_string_append(self, other);
 }
+#endif /* !defined(TRIO_MINIMAL) */
 
 
+#if !defined(TRIO_MINIMAL)
 /*
  * trio_xstring_copy
  */
-TRIO_PUBLIC int
-trio_xstring_copy(trio_string_t *self,
-		  const char *other)
+TRIO_STRING_PUBLIC int
+trio_xstring_copy
+TRIO_ARGS2((self, other),
+	   trio_string_t *self,
+	   TRIO_CONST char *other)
 {
   assert(self);
   assert(other);
@@ -1412,13 +1596,17 @@
   self->length = 0;
   return trio_xstring_append(self, other);
 }
+#endif /* !defined(TRIO_MINIMAL) */
 
 
+#if !defined(TRIO_MINIMAL)
 /*
  * trio_string_duplicate
  */
-TRIO_PUBLIC trio_string_t *
-trio_string_duplicate(trio_string_t *other)
+TRIO_STRING_PUBLIC trio_string_t *
+trio_string_duplicate
+TRIO_ARGS1((other),
+	   trio_string_t *other)
 {
   trio_string_t *self;
   
@@ -1440,13 +1628,16 @@
     }
   return self;
 }
+#endif /* !defined(TRIO_MINIMAL) */
 
 
 /*
  * trio_xstring_duplicate
  */
-TRIO_PUBLIC trio_string_t *
-trio_xstring_duplicate(const char *other)
+TRIO_STRING_PUBLIC trio_string_t *
+trio_xstring_duplicate
+TRIO_ARGS1((other),
+	   TRIO_CONST char *other)
 {
   trio_string_t *self;
   
@@ -1470,168 +1661,215 @@
 }
 
 
+#if !defined(TRIO_MINIMAL)
 /*
  * trio_string_equal
  */
-TRIO_PUBLIC int
-trio_string_equal(trio_string_t *self,
-		  trio_string_t *other)
+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_PUBLIC int
-trio_xstring_equal(trio_string_t *self,
-		   const char *other)
+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_PUBLIC int
-trio_string_equal_max(trio_string_t *self,
-		      size_t max,
-		      trio_string_t *other)
+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_PUBLIC int
-trio_xstring_equal_max(trio_string_t *self,
-		       size_t max,
-		       const char *other)
+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_PUBLIC int
-trio_string_equal_case(trio_string_t *self,
-		       trio_string_t *other)
+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_PUBLIC int
-trio_xstring_equal_case(trio_string_t *self,
-			const char *other)
+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_PUBLIC int
-trio_string_equal_case_max(trio_string_t *self,
-			   size_t max,
-			   trio_string_t *other)
+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_PUBLIC int
-trio_xstring_equal_case_max(trio_string_t *self,
-			    size_t max,
-			    const char *other)
+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_PUBLIC size_t
-trio_string_format_date_max(trio_string_t *self,
-			    size_t max,
-			    const char *format,
-			    const struct tm *datetime)
+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_PUBLIC char *
-trio_string_index(trio_string_t *self,
-		  int character)
+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_PUBLIC char *
-trio_string_index_last(trio_string_t *self,
-		       int character)
+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_PUBLIC int
-trio_string_length(trio_string_t *self)
+TRIO_STRING_PUBLIC int
+trio_string_length
+TRIO_ARGS1((self),
+	   trio_string_t *self)
 {
   assert(self);
 
@@ -1641,113 +1879,146 @@
     }
   return self->length;
 }
+#endif /* !defined(TRIO_MINIMAL) */
 
 
+#if !defined(TRIO_MINIMAL)
 /*
  * trio_string_lower
  */
-TRIO_PUBLIC int
-trio_string_lower(trio_string_t *self)
+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_PUBLIC int
-trio_string_match(trio_string_t *self,
-		  trio_string_t *other)
+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_PUBLIC int
-trio_xstring_match(trio_string_t *self,
-		   const char *other)
+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_PUBLIC int
-trio_string_match_case(trio_string_t *self,
-		       trio_string_t *other)
+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_PUBLIC int
-trio_xstring_match_case(trio_string_t *self,
-			const char *other)
+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_PUBLIC char *
-trio_string_substring(trio_string_t *self,
-		      trio_string_t *other)
+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_PUBLIC char *
-trio_xstring_substring(trio_string_t *self,
-		       const char *other)
+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_PUBLIC int
-trio_string_upper(trio_string_t *self)
+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/triostr.h b/triostr.h
index 94b01ee..083e2a5 100644
--- a/triostr.h
+++ b/triostr.h
@@ -31,42 +31,50 @@
   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
  */
 
-int trio_append(char *target, const char *source);
-int trio_append_max(char *target, size_t max, const char *source);
-int trio_contains(const char *string, const char *substring);
-int trio_copy(char *target, const char *source);
-int trio_copy_max(char *target, size_t max, const char *source);
-char *trio_create(size_t size);
-void trio_destroy(char *string);
-char *trio_duplicate(const char *source);
-char *trio_duplicate_max(const char *source, size_t max);
-int trio_equal(const char *first, const char *second);
-int trio_equal_case(const char *first, const char *second);
-int trio_equal_case_max(const char *first, size_t max, const char *second);
-int trio_equal_locale(const char *first, const char *second);
-int trio_equal_max(const char *first, size_t max, const char *second);
-const char *trio_error(int);
-size_t trio_format_date_max(char *target, size_t max, const char *format, const struct tm *datetime);
-unsigned long trio_hash(const char *string, int type);
-char *trio_index(const char *string, char character);
-char *trio_index_last(const char *string, char character);
-size_t trio_length(const char *string);
-int trio_lower(char *target);
-int trio_match(const char *string, const char *pattern);
-int trio_match_case(const char *string, const char *pattern);
-size_t trio_span_function(char *target, const char *source, int (*Function)(int));
-char *trio_substring(const char *string, const char *substring);
-char *trio_substring_max(const char *string, size_t max, const char *substring);
-char *trio_tokenize(char *string, const char *delimiters);
-float trio_to_float(const char *source, const char **endp);
-double trio_to_double(const char *source, const char **endp);
-long trio_to_long(const char *source, char **endp, int base);
-unsigned long trio_to_unsigned_long(const char *source, char **endp, int base);
-int trio_upper(char *target);
+TRIO_STRING_PUBLIC int trio_append TRIO_PROTO((char *target, const char *source));
+TRIO_STRING_PUBLIC int trio_append_max TRIO_PROTO((char *target, size_t max, const char *source));
+TRIO_STRING_PUBLIC int trio_contains TRIO_PROTO((const char *string, const char *substring));
+TRIO_STRING_PUBLIC int trio_copy TRIO_PROTO((char *target, const char *source));
+TRIO_STRING_PUBLIC int trio_copy_max TRIO_PROTO((char *target, size_t max, const char *source));
+TRIO_STRING_PUBLIC char *trio_create TRIO_PROTO((size_t size));
+TRIO_STRING_PUBLIC void trio_destroy TRIO_PROTO((char *string));
+TRIO_STRING_PUBLIC char *trio_duplicate TRIO_PROTO((const char *source));
+TRIO_STRING_PUBLIC char *trio_duplicate_max TRIO_PROTO((const char *source, size_t max));
+TRIO_STRING_PUBLIC int trio_equal TRIO_PROTO((const char *first, const char *second));
+TRIO_STRING_PUBLIC int trio_equal_case TRIO_PROTO((const char *first, const char *second));
+TRIO_STRING_PUBLIC int trio_equal_case_max TRIO_PROTO((const char *first, size_t max, const char *second));
+TRIO_STRING_PUBLIC int trio_equal_locale TRIO_PROTO((const char *first, const char *second));
+TRIO_STRING_PUBLIC int trio_equal_max TRIO_PROTO((const char *first, size_t max, const char *second));
+TRIO_STRING_PUBLIC TRIO_CONST char *trio_error TRIO_PROTO((int));
+TRIO_STRING_PUBLIC size_t trio_format_date_max TRIO_PROTO((char *target, size_t max, const char *format, const struct tm *datetime));
+TRIO_STRING_PUBLIC unsigned long trio_hash TRIO_PROTO((const char *string, int type));
+TRIO_STRING_PUBLIC char *trio_index TRIO_PROTO((const char *string, int character));
+TRIO_STRING_PUBLIC char *trio_index_last TRIO_PROTO((const char *string, int character));
+TRIO_STRING_PUBLIC size_t trio_length TRIO_PROTO((const char *string));
+TRIO_STRING_PUBLIC int trio_lower TRIO_PROTO((char *target));
+TRIO_STRING_PUBLIC int trio_match TRIO_PROTO((const char *string, const char *pattern));
+TRIO_STRING_PUBLIC int trio_match_case TRIO_PROTO((const char *string, const char *pattern));
+TRIO_STRING_PUBLIC size_t trio_span_function TRIO_PROTO((char *target, const char *source, int (*Function) TRIO_PROTO((int))));
+TRIO_STRING_PUBLIC char *trio_substring TRIO_PROTO((const char *string, const char *substring));
+TRIO_STRING_PUBLIC char *trio_substring_max TRIO_PROTO((const char *string, size_t max, const char *substring));
+TRIO_STRING_PUBLIC double trio_to_double TRIO_PROTO((const char *source, char **endp));
+TRIO_STRING_PUBLIC float trio_to_float TRIO_PROTO((const char *source, char **endp));
+TRIO_STRING_PUBLIC trio_long_double_t trio_to_long_double TRIO_PROTO((const char *source, char **endp));
+TRIO_STRING_PUBLIC long trio_to_long TRIO_PROTO((const char *source, char **endp, int base));
+TRIO_STRING_PUBLIC unsigned long trio_to_unsigned_long TRIO_PROTO((const char *source, char **endp, int base));
+TRIO_STRING_PUBLIC char *trio_tokenize TRIO_PROTO((char *string, const char *delimiters));
+TRIO_STRING_PUBLIC int trio_upper TRIO_PROTO((char *target));
 
 /*************************************************************************
  * Dynamic string functions
@@ -77,43 +85,43 @@
  */
 typedef struct _trio_string_t trio_string_t;
 
-trio_string_t *trio_string_create(int initial_size);
-void trio_string_destroy(trio_string_t *self);
-char *trio_string_get(trio_string_t *self, int offset);
-void trio_xstring_set(trio_string_t *self, char *buffer);
-char *trio_string_extract(trio_string_t *self);
-int trio_string_size(trio_string_t *self);
-void trio_string_terminate(trio_string_t *self);
+TRIO_STRING_PUBLIC trio_string_t *trio_string_create TRIO_PROTO((int initial_size));
+TRIO_STRING_PUBLIC void trio_string_destroy TRIO_PROTO((trio_string_t *self));
+TRIO_STRING_PUBLIC char *trio_string_get TRIO_PROTO((trio_string_t *self, int offset));
+TRIO_STRING_PUBLIC void trio_xstring_set TRIO_PROTO((trio_string_t *self, char *buffer));
+TRIO_STRING_PUBLIC char *trio_string_extract TRIO_PROTO((trio_string_t *self));
+TRIO_STRING_PUBLIC int trio_string_size TRIO_PROTO((trio_string_t *self));
+TRIO_STRING_PUBLIC void trio_string_terminate TRIO_PROTO((trio_string_t *self));
 
-int trio_string_append(trio_string_t *self, trio_string_t *other);
-int trio_string_contains(trio_string_t *self, trio_string_t *other);
-int trio_string_copy(trio_string_t *self, trio_string_t *other);
-trio_string_t *trio_string_duplicate(trio_string_t *other);
-int trio_string_equal(trio_string_t *self, trio_string_t *other);
-int trio_string_equal_max(trio_string_t *self, size_t max, trio_string_t *second);
-int trio_string_equal_case(trio_string_t *self, trio_string_t *other);
-int trio_string_equal_case_max(trio_string_t *self, size_t max, trio_string_t *other);
-size_t trio_string_format_date_max(trio_string_t *self, size_t max, const char *format, const struct tm *datetime);
-char *trio_string_index(trio_string_t *self, int character);
-char *trio_string_index_last(trio_string_t *self, int character);
-int trio_string_length(trio_string_t *self);
-int trio_string_lower(trio_string_t *self);
-int trio_string_match(trio_string_t *self, trio_string_t *other);
-int trio_string_match_case(trio_string_t *self, trio_string_t *other);
-char *trio_string_substring(trio_string_t *self, trio_string_t *other);
-int trio_string_upper(trio_string_t *self);
+TRIO_STRING_PUBLIC int trio_string_append TRIO_PROTO((trio_string_t *self, trio_string_t *other));
+TRIO_STRING_PUBLIC int trio_string_contains TRIO_PROTO((trio_string_t *self, trio_string_t *other));
+TRIO_STRING_PUBLIC int trio_string_copy TRIO_PROTO((trio_string_t *self, trio_string_t *other));
+TRIO_STRING_PUBLIC trio_string_t *trio_string_duplicate TRIO_PROTO((trio_string_t *other));
+TRIO_STRING_PUBLIC int trio_string_equal TRIO_PROTO((trio_string_t *self, trio_string_t *other));
+TRIO_STRING_PUBLIC int trio_string_equal_max TRIO_PROTO((trio_string_t *self, size_t max, trio_string_t *second));
+TRIO_STRING_PUBLIC int trio_string_equal_case TRIO_PROTO((trio_string_t *self, trio_string_t *other));
+TRIO_STRING_PUBLIC int trio_string_equal_case_max TRIO_PROTO((trio_string_t *self, size_t max, trio_string_t *other));
+TRIO_STRING_PUBLIC size_t trio_string_format_date_max TRIO_PROTO((trio_string_t *self, size_t max, const char *format, const struct tm *datetime));
+TRIO_STRING_PUBLIC char *trio_string_index TRIO_PROTO((trio_string_t *self, int character));
+TRIO_STRING_PUBLIC char *trio_string_index_last TRIO_PROTO((trio_string_t *self, int character));
+TRIO_STRING_PUBLIC int trio_string_length TRIO_PROTO((trio_string_t *self));
+TRIO_STRING_PUBLIC int trio_string_lower TRIO_PROTO((trio_string_t *self));
+TRIO_STRING_PUBLIC int trio_string_match TRIO_PROTO((trio_string_t *self, trio_string_t *other));
+TRIO_STRING_PUBLIC int trio_string_match_case TRIO_PROTO((trio_string_t *self, trio_string_t *other));
+TRIO_STRING_PUBLIC char *trio_string_substring TRIO_PROTO((trio_string_t *self, trio_string_t *other));
+TRIO_STRING_PUBLIC int trio_string_upper TRIO_PROTO((trio_string_t *self));
 
-int trio_xstring_append_char(trio_string_t *self, char character);
-int trio_xstring_append(trio_string_t *self, const char *other);
-int trio_xstring_contains(trio_string_t *self, const char *other);
-int trio_xstring_copy(trio_string_t *self, const char *other);
-trio_string_t *trio_xstring_duplicate(const char *other);
-int trio_xstring_equal(trio_string_t *self, const char *other);
-int trio_xstring_equal_max(trio_string_t *self, size_t max, const char *other);
-int trio_xstring_equal_case(trio_string_t *self, const char *other);
-int trio_xstring_equal_case_max(trio_string_t *self, size_t max, const char *other);
-int trio_xstring_match(trio_string_t *self, const char *other);
-int trio_xstring_match_case(trio_string_t *self, const char *other);
-char *trio_xstring_substring(trio_string_t *self, const char *other);
+TRIO_STRING_PUBLIC int trio_xstring_append_char TRIO_PROTO((trio_string_t *self, char character));
+TRIO_STRING_PUBLIC int trio_xstring_append TRIO_PROTO((trio_string_t *self, const char *other));
+TRIO_STRING_PUBLIC int trio_xstring_contains TRIO_PROTO((trio_string_t *self, const char *other));
+TRIO_STRING_PUBLIC int trio_xstring_copy TRIO_PROTO((trio_string_t *self, const char *other));
+TRIO_STRING_PUBLIC trio_string_t *trio_xstring_duplicate TRIO_PROTO((const char *other));
+TRIO_STRING_PUBLIC int trio_xstring_equal TRIO_PROTO((trio_string_t *self, const char *other));
+TRIO_STRING_PUBLIC int trio_xstring_equal_max TRIO_PROTO((trio_string_t *self, size_t max, const char *other));
+TRIO_STRING_PUBLIC int trio_xstring_equal_case TRIO_PROTO((trio_string_t *self, const char *other));
+TRIO_STRING_PUBLIC int trio_xstring_equal_case_max TRIO_PROTO((trio_string_t *self, size_t max, const char *other));
+TRIO_STRING_PUBLIC int trio_xstring_match TRIO_PROTO((trio_string_t *self, const char *other));
+TRIO_STRING_PUBLIC int trio_xstring_match_case TRIO_PROTO((trio_string_t *self, const char *other));
+TRIO_STRING_PUBLIC char *trio_xstring_substring TRIO_PROTO((trio_string_t *self, const char *other));
 
 #endif /* TRIO_TRIOSTR_H */