Upgraded to trio baseline 1.4
diff --git a/trio.c b/trio.c
index 241d6c2..ea772ba 100644
--- a/trio.c
+++ b/trio.c
@@ -27,7 +27,6 @@
 /*
  * TODO:
  *  - Scan is probably too permissive about its modifiers.
- *  - Add hex-float to TrioReadDouble.
  *  - C escapes in %#[] ?
  *  - C99 support has not been properly tested.
  *  - Multibyte characters (done for format parsing, except scan groups)
@@ -39,130 +38,241 @@
  *    %as or %a[ it is interpreted as the alloc modifier, otherwise as
  *    the C99 hex-float. This means that you cannot scan %as as a hex-float
  *    immediately followed by an 's'.
+ *  - Scanning of collating symbols.
  */
 
 static const char rcsid[] = "@(#)$Id$";
 
-#if defined(unix) || defined(__xlC__) /* AIX xlC workaround */
-# define PLATFORM_UNIX
-#elif defined(AMIGA) && defined(__GNUC__)
-# define PLATFORM_UNIX
-#endif
-
 /*************************************************************************
- * Include files
+ * Trio include files
  */
-
 #include "trio.h"
 #include "triop.h"
 #include "strio.h"
 
-#if !defined(DEBUG) && !defined(NDEBUG)
-# define NDEBUG
-#endif
-#include <assert.h>
-#include <ctype.h>
-#include <math.h>
-#include <limits.h>
-#include <float.h>
-#include <stdarg.h>
-#include <errno.h>
-#if defined(TRIO_C99)
-# include <stdint.h>
-#endif
-#if defined(PLATFORM_UNIX)
-# include <unistd.h>
-# include <locale.h>
-# define USE_LOCALE
-#endif
-
-#if defined(_MSC_VER)
-#include <io.h>
-#define read _read
-#define write _write
-#endif /* _MSC_VER */
-
-/*************************************************************************
- * Generic definitions
- */
-
-#ifndef NULL
-# define NULL 0
-#endif
-#define NIL ((char)0)
-#ifdef __cplusplus
-# undef TRUE
-# undef FALSE
-# define TRUE true
-# define FALSE false
-# define BOOLEAN_T bool
-#else
-# ifndef FALSE
-#  define FALSE (1 == 0)
-#  define TRUE (! FALSE)
-# endif
-# define BOOLEAN_T int
-#endif
-
-/* mincore() can be used for debugging purposes */
-#define VALID(x) (NULL != (x))
-
 /*
  * Encode the error code and the position. This is decoded
  * with TRIO_ERROR_CODE and TRIO_ERROR_POSITION.
  */
-#if defined(TRIO_ERRORS)
+#if TRIO_ERRORS
 # define TRIO_ERROR_RETURN(x,y) (- ((x) + ((y) << 8)))
 #else
 # define TRIO_ERROR_RETURN(x,y) (-1)
 #endif
 
-/*************************************************************************
- * Internal definitions
- */
 
-#if defined(__STDC_ISO_10646__) || defined(MB_LEN_MAX)
-# define USE_MULTIBYTE
+/*************************************************************************
+ * Platform and compiler support detection
+ */
+#if defined(unix) || defined(__xlC__) || defined(_AIX) || defined(__QNX__)
+# define PLATFORM_UNIX
+#elif defined(AMIGA) && defined(__GNUC__)
+# define PLATFORM_UNIX
+#elif defined(WIN32) || defined(_WIN32) || defined(_MSC_VER)
+# define PLATFORM_WIN32
+# define TRIO_MSVC_5 1100
 #endif
 
-#if !defined(USE_LONGLONG)
-# if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-#  define USE_LONGLONG
-# elif defined(__SUNPRO_C)
-#  define USE_LONGLONG
-# elif defined(_LONG_LONG) || defined(_LONGLONG)
-#  define USE_LONGLONG
+#if defined(__STDC__) && defined(__STDC_VERSION__)
+# if (__STDC_VERSION__ >= 199409L)
+#  define TRIO_COMPILER_SUPPORTS_ISO94
+# endif
+# if (__STDC_VERSION__ >= 199901L)
+#  define TRIO_COMPILER_SUPPORTS_C99
+# endif
+#endif
+
+#if defined(_XOPEN_SOURCE) && defined(_XOPEN_SOURCE_EXTENDED)
+# define TRIO_COMPILER_SUPPORTS_UNIX98
+#endif
+
+#if defined(__STDC_ISO_10646__) || defined(MB_LEN_MAX) || defined(USE_MULTIBYTE) || TRIO_WIDECHAR
+# define TRIO_COMPILER_SUPPORTS_MULTIBYTE
+# if !defined(MB_LEN_MAX)
+#  define MB_LEN_MAX 6
+# endif
+#endif
+
+
+/*************************************************************************
+ * Generic definitions
+ */
+
+#if !(defined(DEBUG) || defined(NDEBUG))
+# define NDEBUG
+#endif
+#include <assert.h>
+#include <ctype.h>
+#if !defined(TRIO_COMPILER_SUPPORTS_C99)
+# define isblank(x) (((x)==32) || ((x)==9))
+#endif
+#include <math.h>
+#include <limits.h>
+#include <float.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <errno.h>
+
+#ifndef NULL
+# define NULL 0
+#endif
+#define NIL ((char)0)
+#ifndef FALSE
+# define FALSE (1 == 0)
+# define TRUE (! FALSE)
+#endif
+#define BOOLEAN_T int
+
+/* mincore() can be used for debugging purposes */
+#define VALID(x) (NULL != (x))
+
+/* xlC crashes on log10(0) */
+#define guarded_log10(x) (((x) == 0.0) ? -HUGE_VAL : log10(x))
+#define guarded_log16(x) (guarded_log10(x) / log10(16.0))
+
+
+/*************************************************************************
+ * Platform specific definitions
+ */
+#if defined(PLATFORM_UNIX)
+# include <unistd.h>
+# include <signal.h>
+# include <locale.h>
+# define USE_LOCALE
+#endif /* PLATFORM_UNIX */
+#if defined(PLATFORM_WIN32)
+# include <io.h>
+# define read _read
+# define write _write
+#endif /* PLATFORM_WIN32 */
+
+#if TRIO_WIDECHAR
+# if defined(TRIO_COMPILER_SUPPORTS_ISO94)
+#  include <wchar.h>
+#  include <wctype.h>
+# else
+typedef char wchar_t;
+typedef int wint_t;
+#  define WEOF EOF
+#  define iswalnum(x) isalnum(x)
+#  define iswalpha(x) isalpha(x)
+#  define iswblank(x) isblank(x)
+#  define iswcntrl(x) iscntrl(x)
+#  define iswdigit(x) isdigit(x)
+#  define iswgraph(x) isgraph(x)
+#  define iswlower(x) islower(x)
+#  define iswprint(x) isprint(x)
+#  define iswpunct(x) ispunct(x)
+#  define iswspace(x) isspace(x)
+#  define iswupper(x) isupper(x)
+#  define iswxdigit(x) isxdigit(x)
+# endif
+#endif
+
+
+/*************************************************************************
+ * Compiler dependent definitions
+ */
+
+/* Support for long long */
+#ifndef __cplusplus
+# if !defined(USE_LONGLONG)
+#  if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+#   define USE_LONGLONG
+#  elif defined(__SUNPRO_C)
+#   define USE_LONGLONG
+#  elif defined(_LONG_LONG) || defined(_LONGLONG)
+#   define USE_LONGLONG
+#  endif
 # endif
 #endif
 
 /* The extra long numbers */
 #if defined(USE_LONGLONG)
-# define LONGLONG long long
-# define ULONGLONG unsigned long long
+typedef signed long long int trio_longlong_t;
+typedef unsigned long long int trio_ulonglong_t;
+#elif defined(_MSC_VER)
+# if (_MSC_VER >= TRIO_MSVC_5)
+typedef signed __int64 trio_longlong_t;
+typedef unsigned __int64 trio_ulonglong_t;
+# else
+typedef signed long int trio_longlong_t;
+typedef unsigned long int trio_ulonglong_t;
+# endif
 #else
-# define LONGLONG long
-# define ULONGLONG unsigned long
+typedef signed long int trio_longlong_t;
+typedef unsigned long int trio_ulonglong_t;
 #endif
 
-/* The longest possible integer */
-#if defined(TRIO_C99)
-# define LONGEST uintmax_t
-# define SLONGEST intmax_t
+/* Maximal and fixed integer types */
+#if defined(TRIO_COMPILER_SUPPORTS_C99)
+# include <stdint.h>
+typedef intmax_t trio_intmax_t;
+typedef uintmax_t trio_uintmax_t;
+typedef int8_t trio_int8_t;
+typedef int16_t trio_int16_t;
+typedef int32_t trio_int32_t;
+typedef int64_t trio_int64_t;
+#elif defined(TRIO_COMPILER_SUPPORTS_UNIX98)
+# include <inttypes.h>
+typedef intmax_t trio_intmax_t;
+typedef uintmax_t trio_uintmax_t;
+typedef int8_t trio_int8_t;
+typedef int16_t trio_int16_t;
+typedef int32_t trio_int32_t;
+typedef int64_t trio_int64_t;
+#elif defined(_MSC_VER) && (_MSC_VER >= TRIO_MSVC_5)
+typedef trio_longlong_t trio_intmax_t;
+typedef trio_ulonglong_t trio_uintmax_t;
+typedef __int8 trio_int8_t;
+typedef __int16 trio_int16_t;
+typedef __int32 trio_int32_t;
+typedef __int64 trio_int64_t;
 #else
-# define LONGEST ULONGLONG
-# define SLONGEST LONGLONG
+typedef trio_longlong_t trio_intmax_t;
+typedef trio_ulonglong_t trio_uintmax_t;
+# if defined(TRIO_INT8_T)
+typedef TRIO_INT8_T trio_int8_t;
+# else
+typedef 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;
+# endif
+# if defined(TRIO_INT32_T)
+typedef TRIO_INT32_T trio_int32_t;
+# else
+typedef signed int trio_int32_t;
+# endif
+# if defined(TRIO_INT64_T)
+typedef TRIO_INT64_T trio_int64_t;
+# else
+typedef trio_longlong_t trio_int64_t;
+# endif
 #endif
 
-/* The maximal number of digits are for base 2 */
-#define MAX_CHARS_IN(x) (sizeof(x) * CHAR_BIT + 1)
+
+/*************************************************************************
+ * Internal definitions
+ */
+
+/* Long double sizes */
+#ifdef LDBL_DIG
+# define MAX_MANTISSA_DIGITS LDBL_DIG
+# define MAX_EXPONENT_DIGITS 4
+#else
+# define MAX_MANTISSA_DIGITS DBL_DIG
+# define MAX_EXPONENT_DIGITS 3
+#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)
 
 /* Infinite and Not-A-Number for floating-point */
-#define USE_NON_NUMBERS
-#ifndef NAN
-# define NAN (cos(HUGE_VAL))
-#endif
 #define INFINITE_LOWER "inf"
 #define INFINITE_UPPER "INF"
 #define LONG_INFINITE_LOWER "infinite"
@@ -206,12 +316,14 @@
   FLAGS_ALLOC               = 2 * FLAGS_WIDECHAR,
   FLAGS_IGNORE              = 2 * FLAGS_ALLOC,
   FLAGS_IGNORE_PARAMETER    = 2 * FLAGS_IGNORE,
-  FLAGS_SIZE_PARAMETER      = 2 * FLAGS_IGNORE_PARAMETER,
+  FLAGS_VARSIZE_PARAMETER   = 2 * FLAGS_IGNORE_PARAMETER,
+  FLAGS_FIXED_SIZE          = 2 * FLAGS_VARSIZE_PARAMETER,
   /* Reused flags */
   FLAGS_EXCLUDE             = FLAGS_SHORT,
   FLAGS_USER_DEFINED        = FLAGS_IGNORE,
   /* Compounded flags */
   FLAGS_ALL_VARSIZES        = FLAGS_LONG | FLAGS_QUAD | FLAGS_INTMAX_T | FLAGS_PTRDIFF_T | FLAGS_SIZE_T,
+  FLAGS_ALL_SIZES           = FLAGS_ALL_VARSIZES | FLAGS_SHORTSHORT | FLAGS_SHORT,
 
   NO_POSITION  = -1,
   NO_WIDTH     =  0,
@@ -236,7 +348,7 @@
   MAX_USER_DATA = 256,
   
   /* Maximal length of locale separator strings */
-  MAX_LOCALE_SEPARATOR_LENGTH = 64,
+  MAX_LOCALE_SEPARATOR_LENGTH = MB_LEN_MAX,
   /* Maximal number of integers in grouping */
   MAX_LOCALE_GROUPS = 64
 };
@@ -253,10 +365,10 @@
 #define FORMAT_COUNT     6
 #define FORMAT_PARAMETER 7
 #define FORMAT_GROUP     8
-#if defined(TRIO_GNU)
+#if TRIO_GNU
 # define FORMAT_ERRNO    9
 #endif
-#if defined(TRIO_EXTENSION)
+#if TRIO_EXTENSION
 # define FORMAT_USER_DEFINED 10
 #endif
 
@@ -300,7 +412,7 @@
  * o  Octal
  * p  Pointer
  * s  String
- * S  Widechar string (wchar_t)
+ * S  Widechar string (wchar_t *)
  * u  Unsigned
  * x  Hex
  * X  Hex
@@ -329,18 +441,18 @@
 #define SPECIFIER_GROUP '['
 #define SPECIFIER_UNGROUP ']'
 #define SPECIFIER_COUNT 'n'
-#if defined(TRIO_UNIX98)
+#if TRIO_UNIX98
 # define SPECIFIER_CHAR_UPPER 'C'
 # define SPECIFIER_STRING_UPPER 'S'
 #endif
-#if defined(TRIO_C99)
+#if TRIO_C99
 # define SPECIFIER_HEXFLOAT 'a'
 # define SPECIFIER_HEXFLOAT_UPPER 'A'
 #endif
-#if defined(TRIO_GNU)
+#if TRIO_GNU
 # define SPECIFIER_ERRNO 'm'
 #endif
-#if defined(TRIO_EXTENSION)
+#if TRIO_EXTENSION
 # define SPECIFIER_BINARY 'b'
 # define SPECIFIER_BINARY_UPPER 'B'
 # define SPECIFIER_USER_DEFINED_BEGIN '<'
@@ -428,6 +540,14 @@
  *
  * !  Sticky
  * @  Parameter (for both print and scan)
+ *
+ * I  n-bit Integer
+ *    Numbers:
+ *      The following options exists
+ *        I8  = 8-bit integer
+ *        I16 = 16-bit integer
+ *        I32 = 32-bit integer
+ *        I64 = 64-bit integer
  */
 #define QUALIFIER_POSITION '$'
 #define QUALIFIER_SHORT 'h'
@@ -440,26 +560,30 @@
 #define QUALIFIER_DOT '.'
 #define QUALIFIER_STAR '*'
 #define QUALIFIER_CIRCUMFLEX '^'
-#if defined(TRIO_C99)
+#if TRIO_C99
 # define QUALIFIER_SIZE_T 'z'
 # define QUALIFIER_PTRDIFF_T 't'
 # define QUALIFIER_INTMAX_T 'j'
 #endif
-#if defined(TRIO_BSD) || defined(TRIO_GNU)
+#if TRIO_BSD || TRIO_GNU
 # define QUALIFIER_QUAD 'q'
 #endif
-#if defined(TRIO_GNU)
+#if TRIO_GNU
 # define QUALIFIER_SIZE_T_UPPER 'Z'
 #endif
-#if defined(TRIO_MISC)
+#if TRIO_MISC
 # define QUALIFIER_WIDECHAR 'w'
 #endif
-#if defined(TRIO_EXTENSION)
+#if TRIO_MICROSOFT
+# define QUALIFIER_FIXED_SIZE 'I'
+#endif
+#if TRIO_EXTENSION
 # define QUALIFIER_QUOTE '\''
 # define QUALIFIER_STICKY '!'
 # define QUALIFIER_VARSIZE '&' /* This should remain undocumented */
 # define QUALIFIER_PARAM '@' /* Experimental */
 # define QUALIFIER_COLON ':' /* For scanlists */
+# define QUALIFIER_EQUAL '=' /* For scanlists */
 #endif
 
 
@@ -478,10 +602,13 @@
   int indexAfterSpecifier;
   union {
     char *string;
+#if TRIO_WIDECHAR
+    wchar_t *wstring;
+#endif
     void *pointer;
     union {
-      SLONGEST as_signed;
-      LONGEST as_unsigned;
+      trio_uintmax_t as_signed;
+      trio_intmax_t as_unsigned;
     } number;
     double doubleNumber;
     double *doublePointer;
@@ -496,7 +623,7 @@
 
 /* General trio "class" */
 typedef struct _trio_T {
-  const void *location;
+  void *location;
   void (*OutStream)(struct _trio_T *, int);
   void (*InStream)(struct _trio_T *, int *);
   /*
@@ -545,16 +672,22 @@
  * 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] = ".";
-static char internalThousandSeparator[MAX_LOCALE_SEPARATOR_LENGTH] = ",";
+static char internalDecimalPoint[MAX_LOCALE_SEPARATOR_LENGTH + 1] = ".";
+static char internalThousandSeparator[MAX_LOCALE_SEPARATOR_LENGTH + 1] = ",";
 static char internalGrouping[MAX_LOCALE_GROUPS] = { (char)NO_GROUPING };
 
 static const char internalDigitsLower[] = "0123456789abcdefghijklmnopqrstuvwxyz";
 static const char internalDigitsUpper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-static userdef_T *internalUserDef = NULL;
 static BOOLEAN_T internalDigitsUnconverted = TRUE;
 static int internalDigitArray[128];
+#if TRIO_EXTENSION
+static BOOLEAN_T internalCollationUnconverted = TRUE;
+static char internalCollationArray[MAX_CHARACTER_CLASS][MAX_CHARACTER_CLASS];
+#endif
 
+static volatile trio_callback_t internalEnterCriticalRegion = NULL;
+static volatile trio_callback_t internalLeaveCriticalRegion = NULL;
+static userdef_T *internalUserDef = NULL;
 
 
 /*************************************************************************
@@ -639,6 +772,9 @@
 #if defined(QUALIFIER_PARAM)
     case QUALIFIER_PARAM:
 #endif
+#if defined(QUALIFIER_FIXED_SIZE)
+    case QUALIFIER_FIXED_SIZE:
+#endif
       return TRUE;
     default:
       return FALSE;
@@ -646,6 +782,33 @@
 }
 
 /*************************************************************************
+ * TrioGenerateNan [private]
+ *
+ * Calculating NaN portably is difficult. Some compilers will emit
+ * warnings about divide by zero, and others will simply fail to
+ * generate a NaN.
+ */
+static double
+TrioGenerateNaN(void)
+{
+#if defined(TRIO_COMPILER_SUPPORTS_C99)
+  return nan(NULL);
+#elif defined(DBL_QNAN)
+  return DBL_QNAN;
+#elif defined(PLATFORM_UNIX)
+  double value;
+  void (*signal_handler)(int);
+  
+  signal_handler = signal(SIGFPE, SIG_IGN);
+  value = 0.0 / 0.0;
+  signal(SIGFPE, signal_handler);
+  return value;
+#else
+  return 0.0 / 0.0;
+#endif
+}
+
+/*************************************************************************
  * TrioIsNan [private]
  */
 static int
@@ -688,23 +851,29 @@
 TrioSetLocale(void)
 {
   internalLocaleValues = (struct lconv *)localeconv();
-  if (StrLength(internalLocaleValues->decimal_point) > 0)
+  if (internalLocaleValues)
     {
-      StrCopyMax(internalDecimalPoint,
-		 sizeof(internalDecimalPoint),
-		 internalLocaleValues->decimal_point);
-    }
-  if (StrLength(internalLocaleValues->thousands_sep) > 0)
-    {
-      StrCopyMax(internalThousandSeparator,
-		 sizeof(internalThousandSeparator),
-		 internalLocaleValues->thousands_sep);
-    }
-  if (StrLength(internalLocaleValues->grouping) > 0)
-    {
-      StrCopyMax(internalGrouping,
-		 sizeof(internalGrouping),
-		 internalLocaleValues->grouping);
+      if ((internalLocaleValues->decimal_point) &&
+	  (internalLocaleValues->decimal_point[0] != NIL))
+	{
+	  StrCopyMax(internalDecimalPoint,
+		     sizeof(internalDecimalPoint),
+		     internalLocaleValues->decimal_point);
+	}
+      if ((internalLocaleValues->thousands_sep) &&
+	  (internalLocaleValues->thousands_sep[0] != NIL))
+	{
+	  StrCopyMax(internalThousandSeparator,
+		     sizeof(internalThousandSeparator),
+		     internalLocaleValues->thousands_sep);
+	}
+      if ((internalLocaleValues->grouping) &&
+	  (internalLocaleValues->grouping[0] != NIL))
+	{
+	  StrCopyMax(internalGrouping,
+		     sizeof(internalGrouping),
+		     internalLocaleValues->grouping);
+	}
     }
 }
 #endif /* defined(USE_LOCALE) */
@@ -747,15 +916,22 @@
 {
   userdef_T *def;
   
+  if (internalEnterCriticalRegion)
+    (void)internalEnterCriticalRegion(NULL);
+  
   for (def = internalUserDef; def; def = def->next)
     {
       /* Case-sensitive string comparison */
       if (StrEqualCase(def->name, name))
-	return def;
+	break;
       
       if (prev)
 	*prev = def;
     }
+  
+  if (internalLeaveCriticalRegion)
+    (void)internalLeaveCriticalRegion(NULL);
+  
   return def;
 }
 
@@ -772,7 +948,7 @@
 	       va_list arglist,
 	       void **argarray)
 {
-#if defined(TRIO_ERRORS)
+#if TRIO_ERRORS
   /* Count the number of times a parameter is referenced */
   unsigned short usedEntries[MAX_PARAMETERS];
 #endif
@@ -804,7 +980,7 @@
   char *tmpformat;
 
 
-#if defined(TRIO_ERRORS)
+#if TRIO_ERRORS
   /*
    * The 'parameters' array is not initialized, but we need to
    * know which entries we have used.
@@ -814,13 +990,13 @@
 
   index = 0;
   parameterPosition = 0;
-#if defined(USE_MULTIBYTE)
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
   mblen(NULL, 0);
 #endif
   
   while (format[index])
     {
-#if defined(USE_MULTIBYTE)
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
       if (! isascii(format[index]))
 	{
 	  /*
@@ -831,7 +1007,7 @@
 	  index += (charlen > 0) ? charlen : 1;
 	  continue; /* while */
 	}
-#endif /* defined(USE_MULTIBYTE) */
+#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
       if (CHAR_IDENTIFIER == format[index++])
 	{
 	  if (CHAR_IDENTIFIER == format[index])
@@ -1058,7 +1234,7 @@
 		case QUALIFIER_SIZE_T:
 		  flags |= FLAGS_SIZE_T;
 		  /* Modify flags for later truncation of number */
-		  if (sizeof(size_t) == sizeof(ULONGLONG))
+		  if (sizeof(size_t) == sizeof(trio_ulonglong_t))
 		    flags |= FLAGS_QUAD;
 		  else if (sizeof(size_t) == sizeof(long))
 		    flags |= FLAGS_LONG;
@@ -1068,7 +1244,7 @@
 #if defined(QUALIFIER_PTRDIFF_T)
 		case QUALIFIER_PTRDIFF_T:
 		  flags |= FLAGS_PTRDIFF_T;
-		  if (sizeof(ptrdiff_t) == sizeof(ULONGLONG))
+		  if (sizeof(ptrdiff_t) == sizeof(trio_ulonglong_t))
 		    flags |= FLAGS_QUAD;
 		  else if (sizeof(ptrdiff_t) == sizeof(long))
 		    flags |= FLAGS_LONG;
@@ -1078,9 +1254,9 @@
 #if defined(QUALIFIER_INTMAX_T)
 		case QUALIFIER_INTMAX_T:
 		  flags |= FLAGS_INTMAX_T;
-		  if (sizeof(intmax_t) == sizeof(ULONGLONG))
+		  if (sizeof(trio_intmax_t) == sizeof(trio_ulonglong_t))
 		    flags |= FLAGS_QUAD;
-		  else if (sizeof(intmax_t) == sizeof(long))
+		  else if (sizeof(trio_intmax_t) == sizeof(long))
 		    flags |= FLAGS_LONG;
 		  break;
 #endif
@@ -1091,6 +1267,45 @@
 		  break;
 #endif
 
+#if defined(QUALIFIER_FIXED_SIZE)
+		case QUALIFIER_FIXED_SIZE:
+		  if (flags & FLAGS_FIXED_SIZE)
+		    return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
+
+		  if (flags & (FLAGS_ALL_SIZES | FLAGS_LONGDOUBLE |
+			       FLAGS_WIDECHAR | FLAGS_VARSIZE_PARAMETER))
+		    return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
+
+		  if ((format[index] == '6') &&
+		      (format[index + 1] == '4'))
+		    {
+		      varsize = sizeof(trio_int64_t);
+		      index += 2;
+		    }
+		  else if ((format[index] == '3') &&
+			   (format[index + 1] == '2'))
+		    {
+		      varsize = sizeof(trio_int32_t);
+		      index += 2;
+		    }
+		  else if ((format[index] == '1') &&
+			   (format[index + 1] == '6'))
+		    {
+		      varsize = sizeof(trio_int16_t);
+		      index += 2;
+		    }
+		  else if (format[index] == '8')
+		    {
+		      varsize = sizeof(trio_int8_t);
+		      index++;
+		    }
+		  else
+		    return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
+		  
+		  flags |= FLAGS_FIXED_SIZE;
+		  break;
+#endif
+
 #if defined(QUALIFIER_WIDECHAR)
 		case QUALIFIER_WIDECHAR:
 		  flags |= FLAGS_WIDECHAR;
@@ -1117,7 +1332,7 @@
 		  
 #if defined(QUALIFIER_VARSIZE)
 		case QUALIFIER_VARSIZE:
-		  flags |= FLAGS_SIZE_PARAMETER;
+		  flags |= FLAGS_VARSIZE_PARAMETER;
 		  parameterPosition++;
 		  if (positional)
 		    varsize = parameterPosition;
@@ -1143,7 +1358,7 @@
 	   */
 	  if (flags & FLAGS_WIDTH_PARAMETER)
 	    {
-#if defined(TRIO_ERRORS)
+#if TRIO_ERRORS
 	      usedEntries[width] += 1;
 #endif
 	      parameters[pos].type = FORMAT_PARAMETER;
@@ -1152,7 +1367,7 @@
 	    }
 	  if (flags & FLAGS_PRECISION_PARAMETER)
 	    {
-#if defined(TRIO_ERRORS)
+#if TRIO_ERRORS
 	      usedEntries[precision] += 1;
 #endif
 	      parameters[pos].type = FORMAT_PARAMETER;
@@ -1161,16 +1376,16 @@
 	    }
 	  if (flags & FLAGS_BASE_PARAMETER)
 	    {
-#if defined(TRIO_ERRORS)
+#if TRIO_ERRORS
 	      usedEntries[base] += 1;
 #endif
 	      parameters[pos].type = FORMAT_PARAMETER;
 	      indices[base] = pos;
 	      base = pos++;
 	    }
-	  if (flags & FLAGS_SIZE_PARAMETER)
+	  if (flags & FLAGS_VARSIZE_PARAMETER)
 	    {
-#if defined(TRIO_ERRORS)
+#if TRIO_ERRORS
 	      usedEntries[varsize] += 1;
 #endif
 	      parameters[pos].type = FORMAT_PARAMETER;
@@ -1184,30 +1399,57 @@
 	    {
 #if defined(SPECIFIER_CHAR_UPPER)
 	    case SPECIFIER_CHAR_UPPER:
-	      flags |= FLAGS_LONG;
+	      flags |= FLAGS_WIDECHAR;
 	      /* FALLTHROUGH */
 #endif
 	    case SPECIFIER_CHAR:
+	      if (flags & FLAGS_LONG)
+		flags |= FLAGS_WIDECHAR;
+	      else if (flags & FLAGS_SHORT)
+		flags &= ~FLAGS_WIDECHAR;
 	      parameters[pos].type = FORMAT_CHAR;
 	      break;
 
 #if defined(SPECIFIER_STRING_UPPER)
 	    case SPECIFIER_STRING_UPPER:
-	      flags |= FLAGS_LONG;
+	      flags |= FLAGS_WIDECHAR;
 	      /* FALLTHROUGH */
 #endif
 	    case SPECIFIER_STRING:
+	      if (flags & FLAGS_LONG)
+		flags |= FLAGS_WIDECHAR;
+	      else if (flags & FLAGS_SHORT)
+		flags &= ~FLAGS_WIDECHAR;
 	      parameters[pos].type = FORMAT_STRING;
 	      break;
 
 	    case SPECIFIER_GROUP:
 	      if (TYPE_SCAN == type)
 		{
+		  int depth = 1;
 		  parameters[pos].type = FORMAT_GROUP;
-		  while (format[index])
+		  if (format[index] == QUALIFIER_CIRCUMFLEX)
+		    index++;
+		  if (format[index] == SPECIFIER_UNGROUP)
+		    index++;
+		  if (format[index] == QUALIFIER_MINUS)
+		    index++;
+		  /* Skip nested brackets */
+		  while (format[index] != NIL)
 		    {
-		      if (format[index++] == SPECIFIER_UNGROUP)
-			break; /* while */
+		      if (format[index] == SPECIFIER_GROUP)
+			{
+			  depth++;
+			}
+		      else if (format[index] == SPECIFIER_UNGROUP)
+			{
+			  if (--depth <= 0)
+			    {
+			      index++;
+			      break;
+			    }
+			}
+		      index++;
 		    }
 		}
 	      break;
@@ -1328,7 +1570,7 @@
 			    parameters[pos].flags = FLAGS_USER_DEFINED;
 			    /* Adjust parameters for insertion of new one */
 			    pos++;
-# if defined(TRIO_ERRORS)
+# if TRIO_ERRORS
 			    usedEntries[currentParam] += 1;
 # endif
 			    parameters[pos].type = FORMAT_USER_DEFINED;
@@ -1370,7 +1612,7 @@
               return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
 	    }
 
-#if defined(TRIO_ERRORS)
+#if TRIO_ERRORS
 	  /*  Count the number of times this entry has been used */
 	  usedEntries[currentParam] += 1;
 #endif
@@ -1415,7 +1657,7 @@
 
   for (num = 0; num <= maxParam; num++)
     {
-#if defined(TRIO_ERRORS)
+#if TRIO_ERRORS
       if (usedEntries[num] != 1)
 	{
 	  if (usedEntries[num] == 0) /* gap detected */
@@ -1460,16 +1702,27 @@
 	{
 	case FORMAT_GROUP:
 	case FORMAT_STRING:
-	  parameters[i].data.string = (arglist != NULL)
-	    ? va_arg(arglist, char *)
-	    : (char *)(argarray[num]);
+#if TRIO_WIDECHAR
+	  if (flags & FLAGS_WIDECHAR)
+	    {
+	      parameters[i].data.wstring = (argarray == NULL)
+		? va_arg(arglist, wchar_t *)
+		: (wchar_t *)(argarray[num]);
+	    }
+	  else
+#endif
+	    {
+	      parameters[i].data.string = (argarray == NULL)
+		? va_arg(arglist, char *)
+		: (char *)(argarray[num]);
+	    }
 	  break;
 
 	case FORMAT_POINTER:
 	case FORMAT_COUNT:
 	case FORMAT_USER_DEFINED:
 	case FORMAT_UNKNOWN:
-	  parameters[i].data.pointer = (arglist != NULL)
+	  parameters[i].data.pointer = (argarray == NULL)
 	    ? va_arg(arglist, void *)
 	    : argarray[num];
 	  break;
@@ -1478,44 +1731,54 @@
 	case FORMAT_INT:
 	  if (TYPE_SCAN == type)
 	    {
-              if (arglist != NULL)
+              if (argarray == NULL)
                 parameters[i].data.pointer = 
-                  (LONGEST *)va_arg(arglist, void *);
+                  (trio_uintmax_t *)va_arg(arglist, void *);
               else
                 {
                   if (parameters[i].type == FORMAT_CHAR)
                     parameters[i].data.pointer =
-                      (LONGEST *)((char *)argarray[num]);
+                      (trio_uintmax_t *)((char *)argarray[num]);
                   else if (parameters[i].flags & FLAGS_SHORT)
                     parameters[i].data.pointer =
-                      (LONGEST *)((short *)argarray[num]);
+                      (trio_uintmax_t *)((short *)argarray[num]);
                   else
                     parameters[i].data.pointer =
-                      (LONGEST *)((int *)argarray[num]);
+                      (trio_uintmax_t *)((int *)argarray[num]);
                 }
 	    }
 	  else
 	    {
-#if defined(QUALIFIER_VARSIZE)
-	      if (parameters[i].flags & FLAGS_SIZE_PARAMETER)
+#if defined(QUALIFIER_VARSIZE) || defined(QUALIFIER_FIXED_SIZE)
+	      if ((parameters[i].flags & FLAGS_VARSIZE_PARAMETER) ||
+		  (parameters[i].flags & FLAGS_FIXED_SIZE))
 		{
-		  /*
-		   * Variable sizes are mapped onto the fixed sizes, in
-		   * accordance with integer promotion.
-		   *
-		   * Please note that this may not be portable, as we
-		   * only guess the size, not the layout of the numbers.
-		   * For example, if int is little-endian, and long is
-		   * big-endian, then this will fail.
-		   */
+		  if (parameters[i].flags & FLAGS_VARSIZE_PARAMETER)
+		    {
+		      /*
+		       * Variable sizes are mapped onto the fixed sizes, in
+		       * accordance with integer promotion.
+		       *
+		       * Please note that this may not be portable, as we
+		       * only guess the size, not the layout of the numbers.
+		       * For example, if int is little-endian, and long is
+		       * big-endian, then this will fail.
+		       */
+		      varsize = (int)parameters[parameters[i].varsize].data.number.as_unsigned;
+		    }
+		  else
+		    {
+		      /* Used for the I<bits> modifiers */
+		      varsize = parameters[i].varsize;
+		    }
 		  parameters[i].flags &= ~FLAGS_ALL_VARSIZES;
-		  varsize = (int)parameters[parameters[i].varsize].data.number.as_unsigned;
+		  
 		  if (varsize <= (int)sizeof(int))
 		    ;
 		  else if (varsize <= (int)sizeof(long))
 		    parameters[i].flags |= FLAGS_LONG;
 #if defined(QUALIFIER_INTMAX_T)
-		  else if (varsize <= (int)sizeof(LONGLONG))
+		  else if (varsize <= (int)sizeof(trio_longlong_t))
 		    parameters[i].flags |= FLAGS_QUAD;
 		  else
 		    parameters[i].flags |= FLAGS_INTMAX_T;
@@ -1527,45 +1790,45 @@
 #endif /* defined(QUALIFIER_VARSIZE) */
 #if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
 	      if (parameters[i].flags & FLAGS_SIZE_T)
-		parameters[i].data.number.as_unsigned = (arglist != NULL)
-		  ? (LONGEST)va_arg(arglist, size_t)
-		  : (LONGEST)(*((size_t *)argarray[num]));
+		parameters[i].data.number.as_unsigned = (argarray == NULL)
+		  ? (trio_uintmax_t)va_arg(arglist, size_t)
+		  : (trio_uintmax_t)(*((size_t *)argarray[num]));
 	      else
 #endif
 #if defined(QUALIFIER_PTRDIFF_T)
 	      if (parameters[i].flags & FLAGS_PTRDIFF_T)
-		parameters[i].data.number.as_unsigned = (arglist != NULL)
-		  ? (LONGEST)va_arg(arglist, ptrdiff_t)
-		  : (LONGEST)(*((ptrdiff_t *)argarray[num]));
+		parameters[i].data.number.as_unsigned = (argarray == NULL)
+		  ? (trio_uintmax_t)va_arg(arglist, ptrdiff_t)
+		  : (trio_uintmax_t)(*((ptrdiff_t *)argarray[num]));
 	      else
 #endif
 #if defined(QUALIFIER_INTMAX_T)
 	      if (parameters[i].flags & FLAGS_INTMAX_T)
-		parameters[i].data.number.as_unsigned = (arglist != NULL)
-		  ? (LONGEST)va_arg(arglist, intmax_t)
-		  : (LONGEST)(*((intmax_t *)argarray[num]));
+		parameters[i].data.number.as_unsigned = (argarray == NULL)
+		  ? (trio_uintmax_t)va_arg(arglist, trio_intmax_t)
+		  : (trio_uintmax_t)(*((trio_intmax_t *)argarray[num]));
 	      else
 #endif
 	      if (parameters[i].flags & FLAGS_QUAD)
-		parameters[i].data.number.as_unsigned = (arglist != NULL)
-		  ? (LONGEST)va_arg(arglist, ULONGLONG)
-		  : (LONGEST)(*((ULONGLONG *)argarray[num]));
+		parameters[i].data.number.as_unsigned = (argarray == NULL)
+		  ? (trio_uintmax_t)va_arg(arglist, trio_ulonglong_t)
+		  : (trio_uintmax_t)(*((trio_ulonglong_t *)argarray[num]));
 	      else if (parameters[i].flags & FLAGS_LONG)
-		parameters[i].data.number.as_unsigned = (arglist != NULL)
-		  ? (LONGEST)va_arg(arglist, long)
-		  : (LONGEST)(*((long *)argarray[num]));
+		parameters[i].data.number.as_unsigned = (argarray == NULL)
+		  ? (trio_uintmax_t)va_arg(arglist, long)
+		  : (trio_uintmax_t)(*((long *)argarray[num]));
 	      else
 		{
-		  if (arglist != NULL)
-		    parameters[i].data.number.as_unsigned = (LONGEST)va_arg(arglist, int);
+		  if (argarray == NULL)
+		    parameters[i].data.number.as_unsigned = (trio_uintmax_t)va_arg(arglist, int);
 		  else
 		    {
 		      if (parameters[i].type == FORMAT_CHAR)
-			parameters[i].data.number.as_unsigned = (LONGEST)(*((char *)argarray[num]));
+			parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((char *)argarray[num]));
 		      else if (parameters[i].flags & FLAGS_SHORT)
-			parameters[i].data.number.as_unsigned = (LONGEST)(*((short *)argarray[num]));
+			parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((short *)argarray[num]));
 		      else
-			parameters[i].data.number.as_unsigned = (LONGEST)(*((int *)argarray[num]));
+			parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((int *)argarray[num]));
 		    }
 		}
 	    }
@@ -1577,25 +1840,25 @@
 	   * whereas the rest (width, precision, base) uses an integer.
 	   */
 	  if (parameters[i].flags & FLAGS_USER_DEFINED)
-	    parameters[i].data.pointer = (arglist != NULL)
+	    parameters[i].data.pointer = (argarray == NULL)
 	      ? va_arg(arglist, void *)
 	      : argarray[num];
 	  else
-	    parameters[i].data.number.as_unsigned = (arglist != NULL)
-	      ? (LONGEST)va_arg(arglist, int)
-	      : (LONGEST)(*((int *)argarray[num]));
+	    parameters[i].data.number.as_unsigned = (argarray == NULL)
+	      ? (trio_uintmax_t)va_arg(arglist, int)
+	      : (trio_uintmax_t)(*((int *)argarray[num]));
 	  break;
 
 	case FORMAT_DOUBLE:
 	  if (TYPE_SCAN == type)
 	    {
 	      if (parameters[i].flags & FLAGS_LONG)
-		parameters[i].data.longdoublePointer = (arglist != NULL)
+		parameters[i].data.longdoublePointer = (argarray == NULL)
 		  ? va_arg(arglist, long double *)
 		  : (long double *)((long double *)argarray[num]);
 	      else
                 {
-                  if (arglist != NULL)
+                  if (argarray == NULL)
                     parameters[i].data.doublePointer =
                       va_arg(arglist, double *);
                  else
@@ -1612,12 +1875,12 @@
 	  else
 	    {
 	      if (parameters[i].flags & FLAGS_LONG)
-		parameters[i].data.longdoubleNumber = (arglist != NULL)
+		parameters[i].data.longdoubleNumber = (argarray == NULL)
 		  ? va_arg(arglist, long double)
 		  : (long double)(*((long double *)argarray[num]));
 	      else
 		{
-		  if (arglist != NULL)
+		  if (argarray == NULL)
 		    parameters[i].data.longdoubleNumber = (long double)va_arg(arglist, double);
 		  else
 		    {
@@ -1661,16 +1924,14 @@
  */
 static void
 TrioWriteNumber(trio_T *self,
-		SLONGEST number,
+		trio_uintmax_t number,
 		unsigned long flags,
 		int width,
 		int precision,
 		int base)
 {
   BOOLEAN_T isNegative;
-  char buffer[MAX_CHARS_IN(LONGEST)
-	     * MAX_LOCALE_SEPARATOR_LENGTH
-	     * MAX_LOCALE_GROUPS];
+  char buffer[MAX_CHARS_IN(trio_uintmax_t) * (1 + MAX_LOCALE_SEPARATOR_LENGTH) + 1];
   char *bufferend;
   char *pointer;
   const char *digits;
@@ -1687,13 +1948,14 @@
 
   digits = (flags & FLAGS_UPPER) ? internalDigitsUpper : internalDigitsLower;
 
-  if (flags & FLAGS_UNSIGNED)
-    isNegative = FALSE;
-  else if ((isNegative = (((SLONGEST)number) < 0)))
+  isNegative = (flags & FLAGS_UNSIGNED)
+    ? FALSE
+    : ((trio_intmax_t)number < 0);
+  if (isNegative)
     number = -number;
 
   if (flags & FLAGS_QUAD)
-    number &= (ULONGLONG)-1;
+    number &= (trio_ulonglong_t)-1;
   else if (flags & FLAGS_LONG)
     number &= (unsigned long)-1;
   else
@@ -1841,6 +2103,60 @@
 }
 
 /*************************************************************************
+ * TrioWriteStringCharacter [private]
+ *
+ * Description:
+ *  Output a single character of a string
+ */
+static void
+TrioWriteStringCharacter(trio_T *self,
+			 int ch,
+			 unsigned long flags)
+{
+  if (flags & FLAGS_ALTERNATIVE)
+    {
+      if (! (isprint(ch) || isspace(ch)))
+	{
+	  /*
+	   * Non-printable characters are converted to C escapes or
+	   * \number, if no C escape exists.
+	   */
+	  self->OutStream(self, CHAR_BACKSLASH);
+	  switch (ch)
+	    {
+	    case '\007': self->OutStream(self, 'a'); break;
+	    case '\b': self->OutStream(self, 'b'); break;
+	    case '\f': self->OutStream(self, 'f'); break;
+	    case '\n': self->OutStream(self, 'n'); break;
+	    case '\r': self->OutStream(self, 'r'); break;
+	    case '\t': self->OutStream(self, 't'); break;
+	    case '\v': self->OutStream(self, 'v'); break;
+	    case '\\': self->OutStream(self, '\\'); break;
+	    default:
+	      self->OutStream(self, 'x');
+	      TrioWriteNumber(self, (trio_intmax_t)ch,
+			      FLAGS_UNSIGNED | FLAGS_NILPADDING,
+			      2, 2, BASE_HEX);
+	      break;
+	    }
+	}
+      else if (ch == CHAR_BACKSLASH)
+	{
+	  self->OutStream(self, CHAR_BACKSLASH);
+	  self->OutStream(self, CHAR_BACKSLASH);
+	}
+      else
+	{
+	  self->OutStream(self, ch);
+	}
+    }
+  else
+    {
+      self->OutStream(self, ch);
+    }
+}
+
+/*************************************************************************
  * TrioWriteString [private]
  *
  * Description:
@@ -1890,48 +2206,8 @@
   while (length-- > 0)
     {
       /* The ctype parameters must be an unsigned char (or EOF) */
-      ch = (unsigned char)(*string++);
-      if (flags & FLAGS_ALTERNATIVE)
-	{
-	  if (! (isprint(ch) || isspace(ch)))
-	    {
-	      /*
-	       * Non-printable characters are converted to C escapes or
-	       * \number, if no C escape exists.
-	       */
-	      self->OutStream(self, CHAR_BACKSLASH);
-	      switch (ch)
-		{
-		case '\a': self->OutStream(self, 'a'); break;
-		case '\b': self->OutStream(self, 'b'); break;
-		case '\f': self->OutStream(self, 'f'); break;
-		case '\n': self->OutStream(self, 'n'); break;
-		case '\r': self->OutStream(self, 'r'); break;
-		case '\t': self->OutStream(self, 't'); break;
-		case '\v': self->OutStream(self, 'v'); break;
-		case '\\': self->OutStream(self, '\\'); break;
-		default:
-		  self->OutStream(self, 'x');
-		  TrioWriteNumber(self, (SLONGEST)ch,
-				  FLAGS_UNSIGNED | FLAGS_NILPADDING,
-				  2, 2, BASE_HEX);
-		  break;
-		}
-	    }
-	  else if (ch == CHAR_BACKSLASH)
-	    {
-	      self->OutStream(self, CHAR_BACKSLASH);
-	      self->OutStream(self, CHAR_BACKSLASH);
-	    }
-	  else
-	    {
-	      self->OutStream(self, ch);
-	    }
-	}
-      else
-	{
-	  self->OutStream(self, ch);
-	}
+      ch = (int)((unsigned char)(*string++));
+      TrioWriteStringCharacter(self, ch, flags);
     }
 
   if (flags & FLAGS_LEFTADJUST)
@@ -1944,6 +2220,111 @@
 }
 
 /*************************************************************************
+ * TrioWriteWideStringCharacter [private]
+ *
+ * Description:
+ *  Output a wide string as a multi-byte sequence
+ */
+#if TRIO_WIDECHAR
+static int
+TrioWriteWideStringCharacter(trio_T *self,
+			     wchar_t wch,
+			     unsigned long flags,
+			     int width)
+{
+  int size;
+  int i;
+  int ch;
+  char *string;
+  char buffer[MB_LEN_MAX + 1];
+
+  if (width == NO_WIDTH)
+    width = sizeof(buffer);
+  
+  size = wctomb(buffer, wch);
+  if ((size <= 0) || (size > width) || (buffer[0] == NIL))
+    return 0;
+
+  string = buffer;
+  i = size;
+  while ((width >= i) && (width-- > 0) && (i-- > 0))
+    {
+      /* The ctype parameters must be an unsigned char (or EOF) */
+      ch = (int)((unsigned char)(*string++));
+      TrioWriteStringCharacter(self, ch, flags);
+    }
+  return size;
+}
+#endif /* TRIO_WIDECHAR */
+
+/*************************************************************************
+ * TrioWriteString [private]
+ *
+ * Description:
+ *  Output a wide character string as a multi-byte string
+ */
+#if TRIO_WIDECHAR
+static void
+TrioWriteWideString(trio_T *self,
+		    const wchar_t *wstring,
+		    unsigned long flags,
+		    int width,
+		    int precision)
+{
+  int length;
+  int size;
+
+  assert(VALID(self));
+  assert(VALID(self->OutStream));
+
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
+  mblen(NULL, 0);
+#endif
+  
+  if (wstring == NULL)
+    {
+      TrioWriteString(self, NULL, flags, width, precision);
+      return;
+    }
+  
+  if (NO_PRECISION == precision)
+    {
+      length = INT_MAX;
+    }
+  else
+    {
+      length = precision;
+      width -= length;
+    }
+
+  if (flags & FLAGS_QUOTE)
+    self->OutStream(self, CHAR_QUOTE);
+
+  if (! (flags & FLAGS_LEFTADJUST))
+    {
+      while (width-- > 0)
+	self->OutStream(self, CHAR_ADJUST);
+    }
+
+  while (length > 0)
+    {
+      size = TrioWriteWideStringCharacter(self, *wstring++, flags, length);
+      if (size == 0)
+	break; /* while */
+      length -= size;
+    }
+
+  if (flags & FLAGS_LEFTADJUST)
+    {
+      while (width-- > 0)
+	self->OutStream(self, CHAR_ADJUST);
+    }
+  if (flags & FLAGS_QUOTE)
+    self->OutStream(self, CHAR_QUOTE);
+}
+#endif /* TRIO_WIDECHAR */
+
+/*************************************************************************
  * TrioWriteDouble [private]
  */
 static void
@@ -1957,7 +2338,6 @@
   int charsPerThousand;
   int length;
   double number;
-  double precisionPower;
   double workNumber;
   int integerDigits;
   int fractionDigits;
@@ -1970,18 +2350,16 @@
   BOOLEAN_T isExponentNegative = FALSE;
   BOOLEAN_T isHex;
   const char *digits;
-  char numberBuffer[MAX_CHARS_IN(double)
-		   * MAX_LOCALE_SEPARATOR_LENGTH
-		   * MAX_LOCALE_GROUPS];
+  char numberBuffer[MAX_MANTISSA_DIGITS
+		   * (1 + MAX_LOCALE_SEPARATOR_LENGTH) + 1];
   char *numberPointer;
-  char exponentBuffer[MAX_CHARS_IN(double)];
+  char exponentBuffer[MAX_EXPONENT_DIGITS + 1];
   char *exponentPointer = NULL;
   int groupingIndex;
   char *work;
   int i;
   BOOLEAN_T onlyzero;
-
-  int set_precision = precision;
+  int zeroes = 0;
   
   assert(VALID(self));
   assert(VALID(self->OutStream));
@@ -1989,7 +2367,6 @@
 
   number = (double)longdoubleNumber;
   
-#if defined(USE_NON_NUMBERS)
   /* Look for infinite numbers and non-a-number first */
   switch (TrioIsInfinite(number))
     {
@@ -2024,7 +2401,6 @@
 		      flags, width, precision);
       return;
     }
-#endif /* defined(USE_NON_NUMBERS) */
 
   /* Normal numbers */
   digits = (flags & FLAGS_UPPER) ? internalDigitsUpper : internalDigitsLower;
@@ -2033,26 +2409,39 @@
   
   if (precision == NO_PRECISION)
     precision = FLT_DIG;
-  precisionPower = pow(10.0, (double)precision);
   
   isNegative = (number < 0.0);
   if (isNegative)
     number = -number;
-  
+
   if ((flags & FLAGS_FLOAT_G) || isHex)
     {
-      if ((number < 1.0e-4) || (number > precisionPower))
-	flags |= FLAGS_FLOAT_E;
-#if defined(TRIO_UNIX98)
       if (precision == 0)
 	precision = 1;
-#endif
+
+      if ((number < 1.0e-4) || (number > pow(10.0, (double)precision)))
+	{
+	  /* Use scientific notation */
+	  flags |= FLAGS_FLOAT_E;
+	}
+      else if (number < 1.0)
+	{
+	  /*
+	   * Use normal notation. If the integer part of the number is
+	   * zero, then adjust the precision to include leading fractional
+	   * zeros.
+	   */
+	  workNumber = fabs(guarded_log10(number));
+	  if (workNumber - floor(workNumber) < 0.001)
+	    workNumber--;
+	  zeroes = (int)floor(workNumber);
+	}
     }
 
   if (flags & FLAGS_FLOAT_E)
     {
       /* Scale the number */
-      workNumber = log10(number);
+      workNumber = guarded_log10(number);
       if (workNumber == -HUGE_VAL)
 	{
 	  exponent = 0;
@@ -2078,16 +2467,30 @@
    * and number of fractional digits for others
    */
   integerDigits = (floor(number) > DBL_EPSILON)
-    ? 1 + (int)log10(floor(number))
+    ? 1 + (int)guarded_log10(floor(number))
     : 1;
-  fractionDigits = (flags & FLAGS_FLOAT_G)
+  fractionDigits = ((flags & FLAGS_FLOAT_G) && (zeroes == 0))
     ? precision - integerDigits
-    : precision;
-  number = floor(0.5 + number * pow(10.0, (double)fractionDigits));
-  if ((int)log10(number) + 1 > integerDigits + fractionDigits)
+    : zeroes + precision;
+  
+  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)
     {
-      /* Adjust if number was rounded up one digit (ie. 99 to 100) */
-      integerDigits++;
+      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;
+	}
+      else
+	{
+	  /* Adjust if number was rounded up one digit (ie. 99 to 100) */
+	  integerDigits++;
+	}
     }
   
   /* Build the fraction part */
@@ -2099,13 +2502,14 @@
       *(--numberPointer) = digits[(int)fmod(number, dblBase)];
       number = floor(number / dblBase);
 
-      if((set_precision == NO_PRECISION) || (flags & FLAGS_ALTERNATIVE)) {
-        /* Prune trailing zeroes */
-        if (numberPointer[0] != digits[0])
-          onlyzero = FALSE;
-        else if (onlyzero && (numberPointer[0] == digits[0]))
-          numberPointer++;
-      }
+      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++;
+        }
       else
         onlyzero = FALSE;
     }
@@ -2188,9 +2592,8 @@
   if (isNegative || (flags & FLAGS_SHOWSIGN))
     expectedWidth += sizeof("-") - 1;
   if (exponentDigits > 0)
-    expectedWidth += exponentDigits + sizeof("E+") - 1;
-  if (isExponentNegative)
-    expectedWidth += sizeof('-') - 1;
+    expectedWidth += exponentDigits +
+      ((exponentDigits > 1) ? sizeof("E+") : sizeof("E+0")) - 1;
   if (isHex)
     expectedWidth += sizeof("0X") - 1;
   
@@ -2248,6 +2651,11 @@
 		      ? ((flags & FLAGS_UPPER) ? 'P' : 'p')
 		      : ((flags & FLAGS_UPPER) ? 'E' : 'e'));
       self->OutStream(self, (isExponentNegative) ? '-' : '+');
+
+      /* The exponent must contain at least two digits */
+      if (exponentDigits == 1)
+        self->OutStream(self, '0');
+
       for (i = 0; i < exponentDigits; i++)
 	{
 	  self->OutStream(self, exponentPointer[i + 1]);
@@ -2272,7 +2680,7 @@
 		  parameter_T *parameters)
 
 {
-#if defined(USE_MULTIBYTE)
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
   int charlen;
 #endif
   int i;
@@ -2286,13 +2694,13 @@
   
   index = 0;
   i = 0;
-#if defined(USE_MULTIBYTE)
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
   mblen(NULL, 0);
 #endif
   
   while (format[index])
     {
-#if defined(USE_MULTIBYTE)
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
       if (! isascii(format[index]))
 	{
 	  charlen = mblen(&format[index], MB_LEN_MAX);
@@ -2302,7 +2710,7 @@
 	    }
 	  continue; /* while */
 	}
-#endif /* defined(USE_MULTIBYTE) */
+#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
       if (CHAR_IDENTIFIER == format[index])
 	{
 	  if (CHAR_IDENTIFIER == format[index + 1])
@@ -2359,9 +2767,19 @@
 		      while (--width > 0)
 			data->OutStream(data, CHAR_ADJUST);
 		    }
-
-		  data->OutStream(data,
-				  (char)parameters[i].data.number.as_signed);
+#if TRIO_WIDECHAR
+		  if (flags & FLAGS_WIDECHAR)
+		    {
+		      TrioWriteWideStringCharacter(data,
+						   (wchar_t)parameters[i].data.number.as_signed,
+						   flags,
+						   NO_WIDTH);
+		    }
+		  else
+#endif
+		    TrioWriteStringCharacter(data,
+					     (int)parameters[i].data.number.as_signed,
+					     flags);
 
 		  if (flags & FLAGS_LEFTADJUST)
 		    {
@@ -2396,11 +2814,24 @@
 		  break; /* FORMAT_DOUBLE */
 
 		case FORMAT_STRING:
-		  TrioWriteString(data,
-				  parameters[i].data.string,
-				  flags,
-				  width,
-				  precision);
+#if TRIO_WIDECHAR
+		  if (flags & FLAGS_WIDECHAR)
+		    {
+		      TrioWriteWideString(data,
+					  parameters[i].data.wstring,
+					  flags,
+					  width,
+					  precision);
+		    }
+		  else
+#endif
+		    {
+		      TrioWriteString(data,
+				      parameters[i].data.string,
+				      flags,
+				      width,
+				      precision);
+		    }
 		  break; /* FORMAT_STRING */
 
 		case FORMAT_POINTER:
@@ -2434,12 +2865,12 @@
 #endif
 #if defined(QUALIFIER_INTMAX_T)
 		      if (flags & FLAGS_INTMAX_T)
-			*(intmax_t *)pointer = (intmax_t)data->committed;
+			*(trio_intmax_t *)pointer = (trio_intmax_t)data->committed;
 		      else
 #endif
 		      if (flags & FLAGS_QUAD)
 			{
-			  *(ULONGLONG int *)pointer = (ULONGLONG)data->committed;
+			  *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)data->committed;
 			}
 		      else if (flags & FLAGS_LONG)
 			{
@@ -2474,7 +2905,7 @@
 		    {
 		      data->OutStream(data, '#');
 		      TrioWriteNumber(data,
-				      (SLONGEST)parameters[i].data.errorNumber,
+				      (trio_intmax_t)parameters[i].data.errorNumber,
 				      flags,
 				      width,
 				      precision,
@@ -2566,7 +2997,6 @@
 
   assert(VALID(OutStream));
   assert(VALID(format));
-  assert(VALID(arglist) || VALID(argarray));
 
   memset(&data, 0, sizeof(data));
   data.OutStream = OutStream;
@@ -2686,7 +3116,7 @@
   if (infop->buffer == NULL)
     {
       /* Start with a reasonable size */
-      infop->buffer = (char *)malloc(DYNAMIC_START_SIZE);
+      infop->buffer = (char *)TRIO_MALLOC(DYNAMIC_START_SIZE);
       if (infop->buffer == NULL)
 	return; /* fail */
       
@@ -2699,7 +3129,7 @@
       char *newptr;
       
       /* Allocate increasing chunks */
-      newptr = (char *)realloc(infop->buffer, infop->allocated * 2);
+      newptr = (char *)TRIO_REALLOC(infop->buffer, infop->allocated * 2);
       
       if (newptr == NULL)
 	return;
@@ -2708,7 +3138,7 @@
       infop->allocated *= 2;
     }
   
-  infop->buffer[self->committed] = output;
+  infop->buffer[self->committed] = (char)output;
   self->committed++;
   self->processed++;
   
@@ -2738,7 +3168,6 @@
 	     va_list args)
 {
   assert(VALID(format));
-  assert(VALID(args));
 
   return TrioFormat(stdout, 0, TrioOutStreamFile, format, args, NULL);
 }
@@ -2747,10 +3176,11 @@
 trio_printfv(const char *format,
 	     void ** args)
 {
+  va_list dummy;
+  
   assert(VALID(format));
-  assert(VALID(args));
 
-  return TrioFormat(stdout, 0, TrioOutStreamFile, format, NULL, args);
+  return TrioFormat(stdout, 0, TrioOutStreamFile, format, dummy, args);
 }
 
 /*************************************************************************
@@ -2780,7 +3210,6 @@
 {
   assert(VALID(file));
   assert(VALID(format));
-  assert(VALID(args));
   
   return TrioFormat(file, 0, TrioOutStreamFile, format, args, NULL);
 }
@@ -2790,11 +3219,12 @@
 	      const char *format,
 	      void ** args)
 {
+  va_list dummy;
+  
   assert(VALID(file));
   assert(VALID(format));
-  assert(VALID(args));
   
-  return TrioFormat(file, 0, TrioOutStreamFile, format, NULL, args);
+  return TrioFormat(file, 0, TrioOutStreamFile, format, dummy, args);
 }
 
 /*************************************************************************
@@ -2822,7 +3252,6 @@
 	      va_list args)
 {
   assert(VALID(format));
-  assert(VALID(args));
   
   return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, args, NULL);
 }
@@ -2832,10 +3261,11 @@
 	      const char *format,
 	      void **args)
 {
-  assert(VALID(format));
-  assert(VALID(args));
+  va_list dummy;
   
-  return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, NULL, args);
+  assert(VALID(format));
+  
+  return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, dummy, args);
 }
 
 /*************************************************************************
@@ -2868,7 +3298,6 @@
 
   assert(VALID(buffer));
   assert(VALID(format));
-  assert(VALID(args));
 
   status = TrioFormat(&buffer, 0, TrioOutStreamString, format, args, NULL);
   *buffer = NIL;
@@ -2881,12 +3310,12 @@
 	      void **args)
 {
   int status;
+  va_list dummy;
 
   assert(VALID(buffer));
   assert(VALID(format));
-  assert(VALID(args));
 
-  status = TrioFormat(&buffer, 0, TrioOutStreamString, format, NULL, args);
+  status = TrioFormat(&buffer, 0, TrioOutStreamString, format, dummy, args);
   *buffer = NIL;
   return status;
 }
@@ -2925,7 +3354,6 @@
 
   assert(VALID(buffer));
   assert(VALID(format));
-  assert(VALID(args));
 
   status = TrioFormat(&buffer, bufferSize > 0 ? bufferSize - 1 : 0,
 		      TrioOutStreamStringMax, format, args, NULL);
@@ -2941,13 +3369,13 @@
 	       void **args)
 {
   int status;
+  va_list dummy;
 
   assert(VALID(buffer));
   assert(VALID(format));
-  assert(VALID(args));
 
   status = TrioFormat(&buffer, bufferSize > 0 ? bufferSize - 1 : 0,
-		      TrioOutStreamStringMax, format, NULL, args);
+		      TrioOutStreamStringMax, format, dummy, args);
   if (bufferSize > 0)
     *buffer = NIL;
   return status;
@@ -2993,7 +3421,6 @@
   size_t buf_len;
   assert(VALID(buffer));
   assert(VALID(format));
-  assert(VALID(args));
 
   buf_len = strlen(buffer);
   buffer = &buffer[buf_len];
@@ -3040,7 +3467,6 @@
   struct dynamicBuffer info;
 
   assert(VALID(format));
-  assert(VALID(args));
   
   info.buffer = NULL;
   info.length = 0;
@@ -3083,7 +3509,7 @@
      * no memory has been allocated, but we must to allocate and return an
      * empty string.
      */
-    info.buffer = (char *)malloc(sizeof(char));
+    info.buffer = (char *)TRIO_MALLOC(sizeof(char));
     if (info.buffer == NULL) {
       *result = NULL;
       return TRIO_ERROR_RETURN(TRIO_ENOMEM, 0);
@@ -3104,7 +3530,6 @@
   struct dynamicBuffer info;
 
   assert(VALID(format));
-  assert(VALID(args));
 
   info.buffer = NULL;
   info.length = 0;
@@ -3116,7 +3541,7 @@
      return status;
   }
   if (info.length == 0) {
-    info.buffer = (char *)malloc(sizeof(char));
+    info.buffer = (char *)TRIO_MALLOC(sizeof(char));
     if (info.buffer == NULL) {
       *result = NULL;
       return TRIO_ERROR_RETURN(TRIO_ENOMEM, 0);
@@ -3151,6 +3576,20 @@
 
   if (name)
     {
+      /* Handle built-in namespaces */
+      if (name[0] == ':')
+	{
+	  if (StrEqual(name, ":enter"))
+	    {
+	      internalEnterCriticalRegion = callback;
+	    }
+	  else if (StrEqual(name, ":leave"))
+	    {
+	      internalLeaveCriticalRegion = callback;
+	    }
+	  return NULL;
+	}
+      
       /* Bail out if namespace is too long */
       if (StrLength(name) >= MAX_USER_NAME)
 	return NULL;
@@ -3161,9 +3600,12 @@
 	return NULL;
     }
   
-  def = (userdef_T *)malloc(sizeof(userdef_T));
+  def = (userdef_T *)TRIO_MALLOC(sizeof(userdef_T));
   if (def)
     {
+      if (internalEnterCriticalRegion)
+	(void)internalEnterCriticalRegion(NULL);
+      
       if (name)
 	{
 	  /* Link into internal list */
@@ -3178,6 +3620,9 @@
 	? NULL
 	: StrDuplicate(name);
       def->next = NULL;
+
+      if (internalLeaveCriticalRegion)
+	(void)internalLeaveCriticalRegion(NULL);
     }
   return def;
 }
@@ -3199,14 +3644,20 @@
       def = TrioFindNamespace(self->name, &prev);
       if (def)
 	{
+	  if (internalEnterCriticalRegion)
+	    (void)internalEnterCriticalRegion(NULL);
+	  
 	  if (prev == NULL)
 	    internalUserDef = NULL;
 	  else
 	    prev->next = def->next;
+	  
+	  if (internalLeaveCriticalRegion)
+	    (void)internalLeaveCriticalRegion(NULL);
 	}
       StrFree(self->name);
     }
-  free(self);
+  TRIO_FREE(self);
 }
 
 /*************************************************************************
@@ -3510,7 +3961,7 @@
 /*************************************************************************
  * trio_get_largest / trio_set_largest [public]
  */
-#if defined(TRIO_C99)
+#if TRIO_C99
 int
 trio_get_largest(void *ref)
 {
@@ -3531,7 +3982,6 @@
 /*************************************************************************
  * trio_get_ptrdiff / trio_set_ptrdiff [public]
  */
-#if defined(TRIO_C99)
 int
 trio_get_ptrdiff(void *ref)
 {
@@ -3547,12 +3997,11 @@
   else
     ((reference_T *)ref)->parameter->flags &= ~FLAGS_PTRDIFF_T;
 }
-#endif
 
 /*************************************************************************
  * trio_get_size / trio_set_size [public]
  */
-#if defined(TRIO_C99)
+#if TRIO_C99
 int
 trio_get_size(void *ref)
 {
@@ -3580,7 +4029,7 @@
   reference_T *self = (reference_T *)ref;
 
   TrioWriteNumber(self->data,
-		  (SLONGEST)number,
+		  (trio_intmax_t)number,
 		  self->parameter->flags,
 		  self->parameter->width,
 		  self->parameter->precision,
@@ -3597,7 +4046,7 @@
   reference_T *self = (reference_T *)ref;
 
   TrioWriteNumber(self->data,
-		  (SLONGEST)number,
+		  (trio_intmax_t)number,
 		  self->parameter->flags | FLAGS_UNSIGNED,
 		  self->parameter->width,
 		  self->parameter->precision,
@@ -3646,7 +4095,7 @@
 {
   reference_T *self = (reference_T *)ref;
   unsigned long flags;
-  LONGLONG number;
+  trio_uintmax_t number;
 
   if (NULL == pointer)
     {
@@ -3663,14 +4112,14 @@
        * optimising compiler). The (char *) casting is done
        * to please ANSI C++.
        */
-      number = (ULONGLONG)((char *)pointer - (char *)0);
+      number = (trio_uintmax_t)((char *)pointer - (char *)0);
       /* Shrink to size of pointer */
-      number &= (ULONGLONG)-1;
+      number &= (trio_uintmax_t)-1;
       flags = self->parameter->flags;
       flags |= (FLAGS_UNSIGNED | FLAGS_ALTERNATIVE |
 	        FLAGS_NILPADDING);
       TrioWriteNumber(self->data,
-		      number,
+		      (trio_intmax_t)number,
 		      flags,
 		      POINTER_WIDTH,
 		      NO_PRECISION,
@@ -3718,9 +4167,11 @@
 		const char *format,
 		void **argarray)
 {
+  va_list dummy;
+  
   assert(VALID(format));
   
-  return TrioFormatRef((reference_T *)ref, format, NULL, argarray);
+  return TrioFormatRef((reference_T *)ref, format, dummy, argarray);
 }
 
 
@@ -3748,6 +4199,37 @@
 }
 
 /*************************************************************************
+ * TrioGetCollation [private]
+ */
+#if TRIO_EXTENSION
+static void
+TrioGetCollation()
+{
+  int i;
+  int j;
+  int k;
+  char first[2];
+  char second[2];
+
+  /* This is computational expensive */
+  first[1] = NIL;
+  second[1] = NIL;
+  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+    {
+      k = 0;
+      first[0] = (char)i;
+      for (j = 0; j < MAX_CHARACTER_CLASS; j++)
+	{
+	  second[0] = (char)j;
+	  if (StrEqualLocale(first, second))
+	    internalCollationArray[i][k++] = (char)j;
+	}
+      internalCollationArray[i][k] = NIL;
+    }
+}
+#endif
+
+/*************************************************************************
  * TrioGetCharacterClass [private]
  *
  * FIXME:
@@ -3756,7 +4238,7 @@
 static int
 TrioGetCharacterClass(const char *format,
 		      int *indexPointer,
-		      int *flagsPointer,
+		      unsigned long *flagsPointer,
 		      int *characterclass)
 {
   int index = *indexPointer;
@@ -3793,7 +4275,7 @@
     }
   /* Collect characters */
   for (ch = format[index];
-       ch != SPECIFIER_UNGROUP && ch != NIL;
+       (ch != SPECIFIER_UNGROUP) && (ch != NIL);
        ch = format[++index])
     {
       switch (ch)
@@ -3832,103 +4314,170 @@
 	    
 	  ch = range_end;
 	  break;
-
-	case QUALIFIER_COLON: /* Character class expressions */
 	  
-	  if (StrEqualMax(CLASS_ALNUM, sizeof(CLASS_ALNUM) - 1,
-			  &format[index]))
+#if TRIO_EXTENSION
+
+	case SPECIFIER_GROUP:
+	  
+	  switch (format[index + 1])
 	    {
-	      for (i = 0; i < MAX_CHARACTER_CLASS; i++)
-		if (isalnum(i))
-		  characterclass[i]++;
-	      index += sizeof(CLASS_ALNUM) - 1;
-	    }
-	  else if (StrEqualMax(CLASS_ALPHA, sizeof(CLASS_ALPHA) - 1,
-			  &format[index]))
-	    {
-	      for (i = 0; i < MAX_CHARACTER_CLASS; i++)
-		if (isalpha(i))
-		  characterclass[i]++;
-	      index += sizeof(CLASS_ALPHA) - 1;
-	    }
-	  else if (StrEqualMax(CLASS_CNTRL, sizeof(CLASS_CNTRL) - 1,
-			  &format[index]))
-	    {
-	      for (i = 0; i < MAX_CHARACTER_CLASS; i++)
-		if (iscntrl(i))
-		  characterclass[i]++;
-	      index += sizeof(CLASS_CNTRL) - 1;
-	    }
-	  else if (StrEqualMax(CLASS_DIGIT, sizeof(CLASS_DIGIT) - 1,
-			  &format[index]))
-	    {
-	      for (i = 0; i < MAX_CHARACTER_CLASS; i++)
-		if (isdigit(i))
-		  characterclass[i]++;
-	      index += sizeof(CLASS_DIGIT) - 1;
-	    }
-	  else if (StrEqualMax(CLASS_GRAPH, sizeof(CLASS_GRAPH) - 1,
-			  &format[index]))
-	    {
-	      for (i = 0; i < MAX_CHARACTER_CLASS; i++)
-		if (isgraph(i))
-		  characterclass[i]++;
-	      index += sizeof(CLASS_GRAPH) - 1;
-	    }
-	  else if (StrEqualMax(CLASS_LOWER, sizeof(CLASS_LOWER) - 1,
-			  &format[index]))
-	    {
-	      for (i = 0; i < MAX_CHARACTER_CLASS; i++)
-		if (islower(i))
-		  characterclass[i]++;
-	      index += sizeof(CLASS_LOWER) - 1;
-	    }
-	  else if (StrEqualMax(CLASS_PRINT, sizeof(CLASS_PRINT) - 1,
-			  &format[index]))
-	    {
-	      for (i = 0; i < MAX_CHARACTER_CLASS; i++)
-		if (isprint(i))
-		  characterclass[i]++;
-	      index += sizeof(CLASS_PRINT) - 1;
-	    }
-	  else if (StrEqualMax(CLASS_PUNCT, sizeof(CLASS_PUNCT) - 1,
-			  &format[index]))
-	    {
-	      for (i = 0; i < MAX_CHARACTER_CLASS; i++)
-		if (ispunct(i))
-		  characterclass[i]++;
-	      index += sizeof(CLASS_PUNCT) - 1;
-	    }
-	  else if (StrEqualMax(CLASS_SPACE, sizeof(CLASS_SPACE) - 1,
-			  &format[index]))
-	    {
-	      for (i = 0; i < MAX_CHARACTER_CLASS; i++)
-		if (isspace(i))
-		  characterclass[i]++;
-	      index += sizeof(CLASS_SPACE) - 1;
-	    }
-	  else if (StrEqualMax(CLASS_UPPER, sizeof(CLASS_UPPER) - 1,
-			  &format[index]))
-	    {
-	      for (i = 0; i < MAX_CHARACTER_CLASS; i++)
-		if (isupper(i))
-		  characterclass[i]++;
-	      index += sizeof(CLASS_UPPER) - 1;
-	    }
-	  else if (StrEqualMax(CLASS_XDIGIT, sizeof(CLASS_XDIGIT) - 1,
-			  &format[index]))
-	    {
-	      for (i = 0; i < MAX_CHARACTER_CLASS; i++)
-		if (isxdigit(i))
-		  characterclass[i]++;
-	      index += sizeof(CLASS_XDIGIT) - 1;
-	    }
-	  else
-	    {
+	    case QUALIFIER_DOT: /* Collating symbol */
+	      /*
+	       * FIXME: This will be easier to implement when multibyte
+	       * characters have been implemented. Until now, we ignore
+	       * this feature.
+	       */
+	      for (i = index + 2; ; i++)
+		{
+		  if (format[i] == NIL)
+		    /* Error in syntax */
+		    return -1;
+		  else if (format[i] == QUALIFIER_DOT)
+		    break; /* for */
+		}
+	      if (format[++i] != SPECIFIER_UNGROUP)
+		return -1;
+	      
+	      index = i;
+	      break;
+	  
+	    case QUALIFIER_EQUAL: /* Equivalence class expressions */
+	      {
+		unsigned int j;
+		unsigned int k;
+	    
+		if (internalCollationUnconverted)
+		  {
+		    /* Lazy evalutation of collation array */
+		    TrioGetCollation();
+		    internalCollationUnconverted = FALSE;
+		  }
+		for (i = index + 2; ; i++)
+		  {
+		    if (format[i] == NIL)
+		      /* Error in syntax */
+		      return -1;
+		    else if (format[i] == QUALIFIER_EQUAL)
+		      break; /* for */
+		    else
+		      {
+			/* Mark any equivalent character */
+			k = (unsigned int)format[i];
+			for (j = 0; internalCollationArray[k][j] != NIL; j++)
+			  characterclass[(int)internalCollationArray[k][j]]++;
+		      }
+		  }
+		if (format[++i] != SPECIFIER_UNGROUP)
+		  return -1;
+		
+		index = i;
+	      }
+	      break;
+	  
+	    case QUALIFIER_COLON: /* Character class expressions */
+	  
+	      if (StrEqualMax(CLASS_ALNUM, sizeof(CLASS_ALNUM) - 1,
+			      &format[index]))
+		{
+		  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+		    if (isalnum(i))
+		      characterclass[i]++;
+		  index += sizeof(CLASS_ALNUM) - 1;
+		}
+	      else if (StrEqualMax(CLASS_ALPHA, sizeof(CLASS_ALPHA) - 1,
+				   &format[index]))
+		{
+		  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+		    if (isalpha(i))
+		      characterclass[i]++;
+		  index += sizeof(CLASS_ALPHA) - 1;
+		}
+	      else if (StrEqualMax(CLASS_CNTRL, sizeof(CLASS_CNTRL) - 1,
+				   &format[index]))
+		{
+		  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+		    if (iscntrl(i))
+		      characterclass[i]++;
+		  index += sizeof(CLASS_CNTRL) - 1;
+		}
+	      else if (StrEqualMax(CLASS_DIGIT, sizeof(CLASS_DIGIT) - 1,
+				   &format[index]))
+		{
+		  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+		    if (isdigit(i))
+		      characterclass[i]++;
+		  index += sizeof(CLASS_DIGIT) - 1;
+		}
+	      else if (StrEqualMax(CLASS_GRAPH, sizeof(CLASS_GRAPH) - 1,
+				   &format[index]))
+		{
+		  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+		    if (isgraph(i))
+		      characterclass[i]++;
+		  index += sizeof(CLASS_GRAPH) - 1;
+		}
+	      else if (StrEqualMax(CLASS_LOWER, sizeof(CLASS_LOWER) - 1,
+				   &format[index]))
+		{
+		  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+		    if (islower(i))
+		      characterclass[i]++;
+		  index += sizeof(CLASS_LOWER) - 1;
+		}
+	      else if (StrEqualMax(CLASS_PRINT, sizeof(CLASS_PRINT) - 1,
+				   &format[index]))
+		{
+		  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+		    if (isprint(i))
+		      characterclass[i]++;
+		  index += sizeof(CLASS_PRINT) - 1;
+		}
+	      else if (StrEqualMax(CLASS_PUNCT, sizeof(CLASS_PUNCT) - 1,
+				   &format[index]))
+		{
+		  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+		    if (ispunct(i))
+		      characterclass[i]++;
+		  index += sizeof(CLASS_PUNCT) - 1;
+		}
+	      else if (StrEqualMax(CLASS_SPACE, sizeof(CLASS_SPACE) - 1,
+				   &format[index]))
+		{
+		  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+		    if (isspace(i))
+		      characterclass[i]++;
+		  index += sizeof(CLASS_SPACE) - 1;
+		}
+	      else if (StrEqualMax(CLASS_UPPER, sizeof(CLASS_UPPER) - 1,
+				   &format[index]))
+		{
+		  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+		    if (isupper(i))
+		      characterclass[i]++;
+		  index += sizeof(CLASS_UPPER) - 1;
+		}
+	      else if (StrEqualMax(CLASS_XDIGIT, sizeof(CLASS_XDIGIT) - 1,
+				   &format[index]))
+		{
+		  for (i = 0; i < MAX_CHARACTER_CLASS; i++)
+		    if (isxdigit(i))
+		      characterclass[i]++;
+		  index += sizeof(CLASS_XDIGIT) - 1;
+		}
+	      else
+		{
+		  characterclass[(int)ch]++;
+		}
+	      break;
+
+	    default:
 	      characterclass[(int)ch]++;
+	      break;
 	    }
 	  break;
-
+	  
+#endif /* TRIO_EXTENSION */
+	  
 	default:
 	  characterclass[(int)ch]++;
 	  break;
@@ -3945,12 +4494,12 @@
  */
 static BOOLEAN_T
 TrioReadNumber(trio_T *self,
-	       LONGEST *target,
-	       int flags,
+	       trio_uintmax_t *target,
+	       unsigned long flags,
 	       int width,
 	       int base)
 {
-  LONGEST number = 0;
+  trio_uintmax_t number = 0;
   int digit;
   int count;
   BOOLEAN_T isNegative = FALSE;
@@ -3960,6 +4509,18 @@
   assert(VALID(self->InStream));
   assert((base >= MIN_BASE && base <= MAX_BASE) || (base == NO_BASE));
 
+  if (internalDigitsUnconverted)
+    {
+      /* Lazy evaluation of digits array */
+      memset(internalDigitArray, -1, sizeof(internalDigitArray));
+      for (j = 0; j < (int)sizeof(internalDigitsLower) - 1; j++)
+	{
+	  internalDigitArray[(int)internalDigitsLower[j]] = j;
+	  internalDigitArray[(int)internalDigitsUpper[j]] = j;
+	}
+      internalDigitsUnconverted = FALSE;
+    }
+  
   TrioSkipWhitespaces(self);
   
   if (!(flags & FLAGS_UNSIGNED))
@@ -4057,12 +4618,15 @@
 /*************************************************************************
  * TrioReadChar [private]
  */
-static BOOLEAN_T
+static int
 TrioReadChar(trio_T *self,
 	     char *target,
+	     unsigned long flags,
 	     int width)
 {
   int i;
+  char ch;
+  trio_uintmax_t number;
   
   assert(VALID(self));
   assert(VALID(self->InStream));
@@ -4071,11 +4635,48 @@
        (self->current != EOF) && (i < width);
        i++)
     {
-      if (target)
-	target[i] = self->current;
+      ch = (char)self->current;
       self->InStream(self, NULL);
+      if ((flags & FLAGS_ALTERNATIVE) && (ch == CHAR_BACKSLASH))
+	{
+	  switch (self->current)
+	    {
+	    case '\\': ch = '\\'; break;
+	    case 'a': ch = '\007'; break;
+	    case 'b': ch = '\b'; break;
+	    case 'f': ch = '\f'; break;
+	    case 'n': ch = '\n'; break;
+	    case 'r': ch = '\r'; break;
+	    case 't': ch = '\t'; break;
+	    case 'v': ch = '\v'; break;
+	    default:
+	      if (isdigit(self->current))
+		{
+		  /* Read octal number */
+		  if (!TrioReadNumber(self, &number, 0, 3, BASE_OCTAL))
+		    return 0;
+		  ch = (char)number;
+		}
+	      else if (toupper(self->current) == 'X')
+		{
+		  /* Read hexadecimal number */
+		  self->InStream(self, NULL);
+		  if (!TrioReadNumber(self, &number, 0, 2, BASE_HEX))
+		    return 0;
+		  ch = (char)number;
+		}
+	      else
+		{
+		  ch = (char)self->current;
+		}
+	      break;
+	    }
+	}
+      
+      if (target)
+	target[i] = ch;
     }
-  return TRUE;
+  return i + 1;
 }
 
 /*************************************************************************
@@ -4084,12 +4685,10 @@
 static BOOLEAN_T
 TrioReadString(trio_T *self,
 	       char *target,
-	       int flags,
+	       unsigned long flags,
 	       int width)
 {
   int i;
-  char ch;
-  LONGEST number;
   
   assert(VALID(self));
   assert(VALID(self->InStream));
@@ -4105,46 +4704,8 @@
        (! ((self->current == EOF) || isspace(self->current)));
        i++)
     {
-      ch = self->current;
-      if ((flags & FLAGS_ALTERNATIVE) && (ch == CHAR_BACKSLASH))
-	{
-	  self->InStream(self, NULL);
-	  switch (self->current)
-	    {
-	    case '\\': ch = '\\'; break;
-	    case 'a': ch = '\a'; break;
-	    case 'b': ch = '\b'; break;
-	    case 'f': ch = '\f'; break;
-	    case 'n': ch = '\n'; break;
-	    case 'r': ch = '\r'; break;
-	    case 't': ch = '\t'; break;
-	    case 'v': ch = '\v'; break;
-	    default:
-	      if (isdigit(self->current))
-		{
-		  /* Read octal number */
-		  if (!TrioReadNumber(self, &number, 0, 3, BASE_OCTAL))
-		    return FALSE;
-		  ch = (char)number;
-		}
-	      else if (toupper(self->current) == 'X')
-		{
-		  /* Read hexadecimal number */
-		  self->InStream(self, NULL);
-		  if (!TrioReadNumber(self, &number, 0, 2, BASE_HEX))
-		    return FALSE;
-		  ch = (char)number;
-		}
-	      else
-		{
-		  ch = self->current;
-		}
-	      break;
-	    }
-	}
-      if (target)
-	target[i] = ch;
-      self->InStream(self, NULL);
+      if (TrioReadChar(self, &target[i], flags, 1) == 0)
+	break; /* for */
     }
   if (target)
     target[i] = NIL;
@@ -4152,6 +4713,108 @@
 }
 
 /*************************************************************************
+ * TrioReadWideChar [private]
+ */
+#if TRIO_WIDECHAR
+static int
+TrioReadWideChar(trio_T *self,
+		 wchar_t *target,
+		 unsigned long flags,
+		 int width)
+{
+  int i;
+  int j;
+  int size;
+  int amount = 0;
+  wchar_t wch;
+  char buffer[MB_LEN_MAX + 1];
+  
+  assert(VALID(self));
+  assert(VALID(self->InStream));
+
+  for (i = 0;
+       (self->current != EOF) && (i < width);
+       i++)
+    {
+      if (isascii(self->current))
+	{
+	  if (TrioReadChar(self, buffer, flags, 1) == 0)
+	    return 0;
+	  buffer[1] = NIL;
+	}
+      else
+	{
+	  /*
+	   * Collect a multibyte character, by enlarging buffer until
+	   * it contains a fully legal multibyte character, or the
+	   * buffer is full.
+	   */
+	  j = 0;
+	  do
+	    {
+	      buffer[j++] = (char)self->current;
+	      buffer[j] = NIL;
+	      self->InStream(self, NULL);
+	    }
+	  while ((j < (int)sizeof(buffer)) && (mblen(buffer, (size_t)j) != j));
+	}
+      if (target)
+	{
+	  size = mbtowc(&wch, buffer, sizeof(buffer));
+	  if (size > 0)
+	    target[i] = wch;
+	}
+      amount += size;
+      self->InStream(self, NULL);
+    }
+  return amount;
+}
+#endif /* TRIO_WIDECHAR */
+
+/*************************************************************************
+ * TrioReadWideString [private]
+ */
+#if TRIO_WIDECHAR
+static BOOLEAN_T
+TrioReadWideString(trio_T *self,
+		   wchar_t *target,
+		   unsigned long flags,
+		   int width)
+{
+  int i;
+  int size;
+  
+  assert(VALID(self));
+  assert(VALID(self->InStream));
+
+  TrioSkipWhitespaces(self);
+
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
+  mblen(NULL, 0);
+#endif
+  
+  /*
+   * Continue until end of string is reached, a whitespace is encountered,
+   * or width is exceeded
+   */
+  for (i = 0;
+       ((width == NO_WIDTH) || (i < width)) &&
+       (! ((self->current == EOF) || isspace(self->current)));
+       )
+    {
+      size = TrioReadWideChar(self, &target[i], flags, 1);
+      if (size == 0)
+	break; /* for */
+
+      i += size;
+    }
+  if (target)
+    target[i] = L'\0';
+  return TRUE;
+}
+#endif /* TRIO_WIDECHAR */
+
+/*************************************************************************
  * TrioReadGroup [private]
  *
  * FIXME: characterclass does not work with multibyte characters
@@ -4160,7 +4823,7 @@
 TrioReadGroup(trio_T *self,
 	      char *target,
 	      int *characterclass,
-	      int flags,
+	      unsigned long flags,
 	      int width)
 {
   int ch;
@@ -4190,13 +4853,12 @@
  * TrioReadDouble [private]
  *
  * FIXME:
- *  add hex-float format
  *  add long double
  */
 static BOOLEAN_T
 TrioReadDouble(trio_T *self,
 	       double *target,
-	       int flags,
+	       unsigned long flags,
 	       int width)
 {
   int ch;
@@ -4204,6 +4866,7 @@
   int index = 0;
   int start;
   int j;
+  BOOLEAN_T isHex = FALSE;
 
   if ((width == NO_WIDTH) || (width > (int)sizeof(doubleString) - 1))
     width = sizeof(doubleString) - 1;
@@ -4218,13 +4881,12 @@
   ch = self->current;
   if ((ch == '+') || (ch == '-'))
     {
-      doubleString[index++] = ch;
+      doubleString[index++] = (char)ch;
       self->InStream(self, &ch);
       width--;
     }
 
   start = index;
-#if defined(USE_NON_NUMBERS)
   switch (ch)
     {
     case 'n':
@@ -4238,7 +4900,7 @@
       /* Infinity */
       while (isalpha(ch) && (index - start < width))
 	{
-	  doubleString[index++] = ch;
+	  doubleString[index++] = (char)ch;
 	  self->InStream(self, &ch);
 	}
       doubleString[index] = NIL;
@@ -4255,7 +4917,7 @@
       if (StrEqual(doubleString, NAN_LOWER))
 	{
 	  /* NaN must not have a preceeding + nor - */
-	  *target = NAN;
+	  *target = TrioGenerateNaN();
 	  return TRUE;
 	}
       return FALSE;
@@ -4263,14 +4925,24 @@
     default:
       break;
     }
-#endif /* defined(USE_NON_NUMBERS) */
   
+  if (ch == '0')
+    {
+      doubleString[index++] = (char)ch;
+      self->InStream(self, &ch);
+      if (toupper(ch) == 'X')
+	{
+	  isHex = TRUE;
+	  doubleString[index++] = (char)ch;
+	  self->InStream(self, &ch);
+	}
+    }
   while ((ch != EOF) && (index - start < width))
     {
       /* Integer part */
-      if (isdigit(ch))
+      if (isHex ? isxdigit(ch) : isdigit(ch))
 	{
-	  doubleString[index++] = ch;
+	  doubleString[index++] = (char)ch;
 	  self->InStream(self, &ch);
 	}
       else if (flags & FLAGS_QUOTE)
@@ -4294,26 +4966,28 @@
   if (ch == '.')
     {
       /* Decimal part */
-      doubleString[index++] = ch;
+      doubleString[index++] = (char)ch;
       self->InStream(self, &ch);
-      while (isdigit(ch) && (index - start < width))
+      while ((isHex ? isxdigit(ch) : isdigit(ch)) &&
+	     (index - start < width))
 	{
-	  doubleString[index++] = ch;
+	  doubleString[index++] = (char)ch;
 	  self->InStream(self, &ch);
 	}
-      if ((ch == 'e') || (ch == 'E'))
+      if (isHex ? (toupper(ch) == 'P') : (toupper(ch) == 'E'))
 	{
 	  /* Exponent */
-	  doubleString[index++] = ch;
+	  doubleString[index++] = (char)ch;
 	  self->InStream(self, &ch);
 	  if ((ch == '+') || (ch == '-'))
 	    {
-	      doubleString[index++] = ch;
+	      doubleString[index++] = (char)ch;
 	      self->InStream(self, &ch);
 	    }
-	  while (isdigit(ch) && (index - start < width))
+	  while ((isHex ? isxdigit(ch) : isdigit(ch)) &&
+		 (index - start < width))
 	    {
-	      doubleString[index++] = ch;
+	      doubleString[index++] = (char)ch;
 	      self->InStream(self, &ch);
 	    }
 	}
@@ -4323,7 +4997,8 @@
     return FALSE;
   
   if (flags & FLAGS_LONGDOUBLE)
-/*     *longdoublePointer = StrToLongDouble()*/;
+/*     *longdoublePointer = StrToLongDouble()*/
+    return FALSE; /* FIXME: Remove when long double is implemented */
   else
     {
       *target = StrToDouble(doubleString, NULL);
@@ -4337,9 +5012,9 @@
 static BOOLEAN_T
 TrioReadPointer(trio_T *self,
 		void **target,
-		int flags)
+		unsigned long flags)
 {
-  LONGEST number;
+  trio_uintmax_t number;
   char buffer[sizeof(null)];
 
   flags |= (FLAGS_UNSIGNED | FLAGS_ALTERNATIVE | FLAGS_NILPADDING);
@@ -4386,7 +5061,7 @@
 	 va_list arglist,
 	 void **argarray)
 {
-#if defined(USE_MULTIBYTE)
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
   int charlen;
 #endif
   int status;
@@ -4398,19 +5073,18 @@
   int cnt;
   int index; /* Index of format string */
   int i; /* Index of current parameter */
-  int flags;
+  unsigned long flags;
   int width;
   int base;
   void *pointer;
 
   assert(VALID(InStream));
   assert(VALID(format));
-  assert(VALID(arglist) || VALID(argarray));
 
   memset(&internalData, 0, sizeof(internalData));
   data = &internalData;
   data->InStream = InStream;
-  data->location = source;
+  data->location = (void *)source;
   data->max = sourceSize;
 
 #if defined(USE_LOCALE)
@@ -4419,16 +5093,6 @@
       TrioSetLocale();
     }
 #endif
-  if (internalDigitsUnconverted)
-    {
-      memset(internalDigitArray, -1, sizeof(internalDigitArray));
-      for (i = 0; i < (int)sizeof(internalDigitsLower) - 1; i++)
-	{
-	  internalDigitArray[(int)internalDigitsLower[i]] = i;
-	  internalDigitArray[(int)internalDigitsUpper[i]] = i;
-	}
-      internalDigitsUnconverted = FALSE;
-    }
   
   status = TrioPreprocess(TYPE_SCAN, format, parameters, arglist, argarray);
   if (status < 0)
@@ -4439,13 +5103,13 @@
   index = 0;
   data->InStream(data, &ch);
 
-#if defined(USE_MULTIBYTE)
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
   mblen(NULL, 0);
 #endif
 
   while (format[index])
     {
-#if defined(USE_MULTIBYTE)
+#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
       if (! isascii(format[index]))
 	{
 	  charlen = mblen(&format[index], MB_LEN_MAX);
@@ -4460,7 +5124,7 @@
 	    }
 	  continue; /* while */
 	}
-#endif /* defined(USE_MULTIBYTE) */
+#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
       if (EOF == ch)
 	return EOF;
       
@@ -4503,7 +5167,7 @@
 	    {
 	    case FORMAT_INT:
 	      {
-		LONGEST number;
+		trio_uintmax_t number;
 
 		if (0 == base)
 		  base = BASE_DECIMAL;
@@ -4531,11 +5195,11 @@
 #endif
 #if defined(QUALIFIER_INTMAX_T)
 		    if (flags & FLAGS_INTMAX_T)
-		      *(intmax_t *)pointer = (intmax_t)number;
+		      *(trio_intmax_t *)pointer = (trio_intmax_t)number;
 		    else
 #endif
 		    if (flags & FLAGS_QUAD)
-		      *(ULONGLONG int *)pointer = (ULONGLONG)number;
+		      *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)number;
 		    else if (flags & FLAGS_LONG)
 		      *(long int *)pointer = (long int)number;
 		    else if (flags & FLAGS_SHORT)
@@ -4547,13 +5211,28 @@
 	      break; /* FORMAT_INT */
 	      
 	    case FORMAT_STRING:
-	      if (!TrioReadString(data,
-				  (flags & FLAGS_IGNORE)
-				  ? NULL
-				  : parameters[i].data.string,
-				  flags,
-				  width))
-		return assignment;
+#if TRIO_WIDECHAR
+	      if (flags & FLAGS_WIDECHAR)
+		{
+		  if (!TrioReadWideString(data,
+					  (flags & FLAGS_IGNORE)
+					  ? NULL
+					  : parameters[i].data.wstring,
+					  flags,
+					  width))
+		    return assignment;
+		}
+	      else
+#endif
+		{
+		  if (!TrioReadString(data,
+				      (flags & FLAGS_IGNORE)
+				      ? NULL
+				      : parameters[i].data.string,
+				      flags,
+				      width))
+		    return assignment;
+		}
 	      assignment++;
 	      break; /* FORMAT_STRING */
 	      
@@ -4572,10 +5251,19 @@
 	      {
 		int characterclass[MAX_CHARACTER_CLASS + 1];
 		int rc;
+
+		/* Skip over modifiers */
+		while (format[index] != SPECIFIER_GROUP)
+		  {
+		    index++;
+		  }
+		/* Skip over group specifier */
+		index++;
 		
-		index += 2;
 		memset(characterclass, 0, sizeof(characterclass));
-		rc = TrioGetCharacterClass(format, &index, &flags,
+		rc = TrioGetCharacterClass(format,
+					   &index,
+					   &flags,
 					   characterclass);
 		if (rc < 0)
 		  return rc;
@@ -4608,12 +5296,12 @@
 #endif
 #if defined(QUALIFIER_INTMAX_T)
 		  if (flags & FLAGS_INTMAX_T)
-		    *(intmax_t *)pointer = (intmax_t)data->committed;
+		    *(trio_intmax_t *)pointer = (trio_intmax_t)data->committed;
 		  else
 #endif
 		  if (flags & FLAGS_QUAD)
 		    {
-		      *(ULONGLONG int *)pointer = (ULONGLONG)data->committed;
+		      *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)data->committed;
 		    }
 		  else if (flags & FLAGS_LONG)
 		    {
@@ -4631,12 +5319,28 @@
 	      break; /* FORMAT_COUNT */
 	      
 	    case FORMAT_CHAR:
-	      if (!TrioReadChar(data,
-				(flags & FLAGS_IGNORE)
-				? NULL
-				: parameters[i].data.string,
-				(width == NO_WIDTH) ? 1 : width))
-		return assignment;
+#if TRIO_WIDECHAR
+	      if (flags & FLAGS_WIDECHAR)
+		{
+		  if (TrioReadWideChar(data,
+				       (flags & FLAGS_IGNORE)
+				       ? NULL
+				       : parameters[i].data.wstring,
+				       flags,
+				       (width == NO_WIDTH) ? 1 : width) > 0)
+		    return assignment;
+		}
+	      else
+#endif
+		{
+		  if (TrioReadChar(data,
+				   (flags & FLAGS_IGNORE)
+				   ? NULL
+				   : parameters[i].data.string,
+				   flags,
+				   (width == NO_WIDTH) ? 1 : width) > 0)
+		    return assignment;
+		}
 	      assignment++;
 	      break; /* FORMAT_CHAR */
 	      
@@ -4776,7 +5480,6 @@
 	    va_list args)
 {
   assert(VALID(format));
-  assert(VALID(args));
   
   return TrioScan(stdin, 0, TrioInStreamFile, format, args, NULL);
 }
@@ -4785,10 +5488,11 @@
 trio_scanfv(const char *format,
 	    void **args)
 {
-  assert(VALID(format));
-  assert(VALID(args));
+  va_list dummy;
   
-  return TrioScan(stdin, 0, TrioInStreamFile, format, NULL, args);
+  assert(VALID(format));
+  
+  return TrioScan(stdin, 0, TrioInStreamFile, format, dummy, args);
 }
 
 /*************************************************************************
@@ -4818,7 +5522,6 @@
 {
   assert(VALID(file));
   assert(VALID(format));
-  assert(VALID(args));
   
   return TrioScan(file, 0, TrioInStreamFile, format, args, NULL);
 }
@@ -4828,11 +5531,12 @@
 	     const char *format,
 	     void **args)
 {
+  va_list dummy;
+  
   assert(VALID(file));
   assert(VALID(format));
-  assert(VALID(args));
   
-  return TrioScan(file, 0, TrioInStreamFile, format, NULL, args);
+  return TrioScan(file, 0, TrioInStreamFile, format, dummy, args);
 }
 
 /*************************************************************************
@@ -4860,7 +5564,6 @@
 	     va_list args)
 {
   assert(VALID(format));
-  assert(VALID(args));
   
   return TrioScan(&fd, 0, TrioInStreamFileDescriptor, format, args, NULL);
 }
@@ -4870,10 +5573,11 @@
              const char *format,
              void **args)
 {
-  assert(VALID(format));
-  assert(VALID(args));
+  va_list dummy;
   
-  return TrioScan(&fd, 0, TrioInStreamFileDescriptor, format, NULL, args);
+  assert(VALID(format));
+  
+  return TrioScan(&fd, 0, TrioInStreamFileDescriptor, format, dummy, args);
 }
 
 /*************************************************************************
@@ -4903,7 +5607,6 @@
 {
   assert(VALID(buffer));
   assert(VALID(format));
-  assert(VALID(args));
   
   return TrioScan(&buffer, 0, TrioInStreamString, format, args, NULL);
 }
@@ -4913,9 +5616,11 @@
 	     const char *format,
 	     void **args)
 {
+  va_list dummy;
+  
   assert(VALID(buffer));
   assert(VALID(format));
-  assert(VALID(args));
   
-  return TrioScan(&buffer, 0, TrioInStreamString, format, NULL, args);
+  return TrioScan(&buffer, 0, TrioInStreamString, format, dummy, args);
 }
+