]> Pileus Git - ~andy/fetchmail/blobdiff - trio/regression.c
Improve X.509 certificate validation reporting.
[~andy/fetchmail] / trio / regression.c
index ccbd78b5dff2b94bb2f452afb5df35d53bd1bdfd..57c0347e078a69a3dff73104c1df8e29ff041f10 100644 (file)
 
 #include "trio.h"
 #include "triop.h"
+#if defined(TRIO_EMBED_NAN)
+# define TRIO_PUBLIC_NAN static
+# define TRIO_FUNC_NINF
+# define TRIO_FUNC_PINF
+# define TRIO_FUNC_NAN
+# define TRIO_FUNC_ISINF
+# define TRIO_FUNC_ISNAN
+# if TRIO_FEATURE_FLOAT
+#  define TRIO_FUNC_NZERO
+# endif
+#endif
 #include "trionan.h"
-#if defined(TRIO_MINIMAL)
-# define TRIO_STRING_PUBLIC static
-# include "triostr.c"
-#else
-# include "triostr.h"
+#if defined(TRIO_EMBED_STRING)
+# define TRIO_PUBLIC_STRING static
+# define TRIO_FUNC_EQUAL_CASE
 #endif
+#include "triostr.h"
 #undef printf
 
-#if TRIO_WIDECHAR
+#if TRIO_FEATURE_WIDECHAR
 # include <wchar.h>
 #endif
 
 #define DOUBLE_EQUAL(x,y) (((x)>(y)-DBL_EPSILON) && ((x)<(y)+DBL_EPSILON))
 #define FLOAT_EQUAL(x,y) (((x)>(y)-FLT_EPSILON) && ((x)<(y)+FLT_EPSILON))
 
-static TRIO_CONST char rcsid[] = "@(#)$Id: regression.c,v 1.44 2002/12/29 15:08:56 breese Exp $";
+static TRIO_CONST char rcsid[] = "@(#)$Id: regression.c,v 1.67 2010/01/26 13:02:02 breese Exp $";
 
+#if defined(TRIO_EMBED_NAN)
+# include "trionan.c"
+#endif
+#if defined(TRIO_EMBED_STRING)
+# include "triostr.c"
+#endif
 
 /*************************************************************************
  *
@@ -187,6 +203,7 @@ int
 VerifyAllocate(TRIO_NOARGS)
 {
   int nerrors = 0;
+#if TRIO_FEATURE_DYNAMICSTRING
   int rc;
   char *string;
   int count;
@@ -213,7 +230,8 @@ VerifyAllocate(TRIO_NOARGS)
     }
   if (string)
     free(string);
-
+#endif
+  
   return nerrors;
 }
 
@@ -222,10 +240,9 @@ VerifyAllocate(TRIO_NOARGS)
  *
  */
 int
-VerifyFormatting(TRIO_NOARGS)
+VerifyFormattingStrings(TRIO_NOARGS)
 {
   int nerrors = 0;
-  char buffer[256];
 
   /* Normal text */
   nerrors += Verify(__FILE__, __LINE__, "Hello world",
@@ -233,20 +250,19 @@ VerifyFormatting(TRIO_NOARGS)
   /* String */
   nerrors += Verify(__FILE__, __LINE__, "Hello world",
                   "%s", "Hello world");
-  /* Pointer */
-  if (sizeof(void *) == 4)
-    {
-      nerrors += Verify(__FILE__, __LINE__, "Pointer 0x01234567",
-                       "Pointer %p", 0x1234567);
-    }
-  else if (sizeof(void *) == 8)
-    {
-      nerrors += Verify(__FILE__, __LINE__, "Pointer 0x0123456789012345",
-                       "Pointer %p", 0x123456789012345);
-    }
-  /* Nil pointer */
-  nerrors += Verify(__FILE__, __LINE__, "Pointer (nil)",
-                  "Pointer %p", NULL);
+
+  return nerrors;
+}
+
+/*************************************************************************
+ *
+ */
+int
+VerifyFormattingIntegers(TRIO_NOARGS)
+{
+  int nerrors = 0;
+  char buffer[256];
+  
   /* Integer */
   nerrors += Verify(__FILE__, __LINE__, "Number 42",
                   "Number %d", 42);
@@ -341,6 +357,19 @@ VerifyFormatting(TRIO_NOARGS)
   sprintf(buffer, "%x", UINT_MAX);
   nerrors += Verify(__FILE__, __LINE__, buffer,
                    "%x", -1);
+
+  return nerrors;
+}
+
+/*************************************************************************
+ *
+ */
+int
+VerifyFormattingFloats(TRIO_NOARGS)
+{
+  int nerrors = 0;
+
+#if TRIO_FEATURE_FLOAT
   /* Double */
   nerrors += Verify(__FILE__, __LINE__, "3141.000000",
                    "%f", 3141.0);
@@ -377,7 +406,7 @@ VerifyFormatting(TRIO_NOARGS)
   /* Beyond accuracy */
   nerrors += Verify(__FILE__, __LINE__, "0.000000",
                    "%f", 1.234567890123456789e-20);
-#if defined(TRIO_BREESE)
+# if defined(TRIO_BREESE)
   nerrors += Verify(__FILE__, __LINE__, "1.3999999999999999111821580299875",
                    "%.32g", 1.4);
   nerrors += Verify(__FILE__, __LINE__, "1.39999999999999991118215802998748",
@@ -392,7 +421,7 @@ VerifyFormatting(TRIO_NOARGS)
                    "%.14f", 1.4);
   nerrors += Verify(__FILE__, __LINE__, "39413.800000000002910383045673370361",
                    "%.30f", 39413.80);
-#endif
+# endif
   /* 2^-1 + 2^-15 */
   nerrors += Verify(__FILE__, __LINE__, "0.500030517578125",
                    "%.*g", DBL_DIG + 10, 0.500030517578125);
@@ -413,6 +442,8 @@ VerifyFormatting(TRIO_NOARGS)
                    "%#.4f", 0.0);
   nerrors += Verify(__FILE__, __LINE__, "0.000",
                    "%#.4g", 0.0);
+  nerrors += Verify(__FILE__, __LINE__, "0.001000",
+                   "%#.4g", 1e-3);
   nerrors += Verify(__FILE__, __LINE__, "3141.0000",
                    "%#.4f", 3141.0);
   nerrors += Verify(__FILE__, __LINE__, "3141.",
@@ -427,9 +458,11 @@ VerifyFormatting(TRIO_NOARGS)
                    "%.e", 3141.0);
   nerrors += Verify(__FILE__, __LINE__, "3.e+03",
                    "%#.e", 3141.0);
-  nerrors += Verify(__FILE__, __LINE__, "100",
+  nerrors += Verify(__FILE__, __LINE__, "1.23457e+06",
+                   "%g", 1234567.0);
+  nerrors += Verify(__FILE__, __LINE__, "1e+02",
                    "%.2g", 99.9999);
-  nerrors += Verify(__FILE__, __LINE__, "100.",
+  nerrors += Verify(__FILE__, __LINE__, "1.0e+02",
                    "%#.2g", 99.9999);
   nerrors += Verify(__FILE__, __LINE__, "0.123",
                    "%0g", 0.123);
@@ -437,12 +470,110 @@ VerifyFormatting(TRIO_NOARGS)
                    "%.2e", 0.9999);
   nerrors += Verify(__FILE__, __LINE__, "1",
                    "%.2g", 0.9999);
+  nerrors += Verify(__FILE__, __LINE__, "2",
+                   "%.0g", 1.5);
   nerrors += Verify(__FILE__, __LINE__, "2",
                    "%.g", 1.5);
   nerrors += Verify(__FILE__, __LINE__, "0.01",
                    "%.2g", 0.01);
   nerrors += Verify(__FILE__, __LINE__, "0.010",
                    "%#.2g", 0.01);
+  nerrors += Verify(__FILE__, __LINE__, "1e-04",
+                   "%5.g", 0.999999e-4);
+  /* Double width and precision */
+  nerrors += Verify(__FILE__, __LINE__, "      1e-05",
+                   "%11.5g", 1e-5);
+  nerrors += Verify(__FILE__, __LINE__, "     0.0001",
+                   "%11.5g", 1e-4);
+  nerrors += Verify(__FILE__, __LINE__, "      0.001",
+                   "%11.5g", 1e-3);
+  nerrors += Verify(__FILE__, __LINE__, "       0.01",
+                   "%11.5g", 1e-2);
+  nerrors += Verify(__FILE__, __LINE__, "        0.1",
+                   "%11.5g", 1e-1);
+  nerrors += Verify(__FILE__, __LINE__, "          1",
+                   "%11.5g", 1e0);
+  nerrors += Verify(__FILE__, __LINE__, "         10",
+                   "%11.5g", 1e1);
+  nerrors += Verify(__FILE__, __LINE__, "        100",
+                   "%11.5g", 1e2);
+  nerrors += Verify(__FILE__, __LINE__, "       1000",
+                   "%11.5g", 1e3);
+  nerrors += Verify(__FILE__, __LINE__, "      10000",
+                   "%11.5g", 1e4);
+  nerrors += Verify(__FILE__, __LINE__, "      1e+05",
+                   "%11.5g", 1e5);
+  nerrors += Verify(__FILE__, __LINE__, "    9.9e-05",
+                   "%11.2g", 0.99e-4);
+  nerrors += Verify(__FILE__, __LINE__, "    0.00099",
+                   "%11.2g", 0.99e-3);
+  nerrors += Verify(__FILE__, __LINE__, "     0.0099",
+                   "%11.2g", 0.99e-2);
+  nerrors += Verify(__FILE__, __LINE__, "      0.099",
+                   "%11.2g", 0.99e-1);
+  nerrors += Verify(__FILE__, __LINE__, "       0.99",
+                   "%11.2g", 0.99e0);
+  nerrors += Verify(__FILE__, __LINE__, "        9.9",
+                   "%11.2g", 0.99e1);
+  nerrors += Verify(__FILE__, __LINE__, "         99",
+                   "%11.2g", 0.99e2);
+  nerrors += Verify(__FILE__, __LINE__, "    9.9e+02",
+                   "%11.2g", 0.99e3);
+  nerrors += Verify(__FILE__, __LINE__, "    9.9e+03",
+                   "%11.2g", 0.99e4);
+  nerrors += Verify(__FILE__, __LINE__, "    9.9e+04",
+                   "%11.2g", 0.99e5);
+  /* Double width, precision, and alternative */
+  nerrors += Verify(__FILE__, __LINE__, " 1.0000e-05",
+                   "%#11.5g", 1e-5);
+  nerrors += Verify(__FILE__, __LINE__, " 0.00010000",
+                   "%#11.5g", 1e-4);
+  nerrors += Verify(__FILE__, __LINE__, "  0.0010000",
+                   "%#11.5g", 1e-3);
+  nerrors += Verify(__FILE__, __LINE__, "  0.0010000",
+                   "%#11.5g", 0.999999e-3);
+  nerrors += Verify(__FILE__, __LINE__, "   0.010000",
+                   "%#11.5g", 1e-2);
+  nerrors += Verify(__FILE__, __LINE__, "   0.010000",
+                   "%#11.5g", 0.999999e-2);
+  nerrors += Verify(__FILE__, __LINE__, "    0.10000",
+                   "%#11.5g", 1e-1);
+  nerrors += Verify(__FILE__, __LINE__, "    0.10000",
+                   "%#11.5g", 0.999999e-1);
+  nerrors += Verify(__FILE__, __LINE__, "     1.0000",
+                   "%#11.5g", 1e0);
+  nerrors += Verify(__FILE__, __LINE__, "     1.0000",
+                   "%#11.5g", 0.999999e0);
+  nerrors += Verify(__FILE__, __LINE__, "     10.000",
+                   "%#11.5g", 1e1);
+  nerrors += Verify(__FILE__, __LINE__, "     100.00",
+                   "%#11.5g", 1e2);
+  nerrors += Verify(__FILE__, __LINE__, "     1000.0",
+                   "%#11.5g", 1e3);
+  nerrors += Verify(__FILE__, __LINE__, "     10000.",
+                   "%#11.5g", 1e4);
+  nerrors += Verify(__FILE__, __LINE__, " 1.0000e+05",
+                   "%#11.5g", 1e5);
+  nerrors += Verify(__FILE__, __LINE__, "    9.9e-05",
+                   "%#11.2g", 0.99e-4);
+  nerrors += Verify(__FILE__, __LINE__, "    0.00099",
+                   "%#11.2g", 0.99e-3);
+  nerrors += Verify(__FILE__, __LINE__, "     0.0099",
+                   "%#11.2g", 0.99e-2);
+  nerrors += Verify(__FILE__, __LINE__, "      0.099",
+                   "%#11.2g", 0.99e-1);
+  nerrors += Verify(__FILE__, __LINE__, "       0.99",
+                   "%#11.2g", 0.99e0);
+  nerrors += Verify(__FILE__, __LINE__, "        9.9",
+                   "%#11.2g", 0.99e1);
+  nerrors += Verify(__FILE__, __LINE__, "        99.",
+                   "%#11.2g", 0.99e2);
+  nerrors += Verify(__FILE__, __LINE__, "    9.9e+02",
+                   "%#11.2g", 0.99e3);
+  nerrors += Verify(__FILE__, __LINE__, "    9.9e+03",
+                   "%#11.2g", 0.99e4);
+  nerrors += Verify(__FILE__, __LINE__, "    9.9e+04",
+                   "%#11.2g", 0.99e5);
   /* Double width, precision, and zero padding */
   nerrors += Verify(__FILE__, __LINE__, "00003.141500e+03",
                    "%016e", 3141.5);
@@ -477,6 +608,134 @@ VerifyFormatting(TRIO_NOARGS)
   nerrors += Verify(__FILE__, __LINE__, "NAN",
                    "%F", trio_nan());
   
+# if TRIO_FEATURE_HEXFLOAT
+  nerrors += Verify(__FILE__, __LINE__, "0x2.ap+4",
+                   "%a", 42.0);
+  nerrors += Verify(__FILE__, __LINE__, "-0x2.ap+4",
+                   "%a", -42.0);
+  nerrors += Verify(__FILE__, __LINE__, "0x1.8p+0",
+                   "%a", 1.5);
+  nerrors += Verify(__FILE__, __LINE__, "0x1.6666666666666p+0",
+                   "%a", 1.4);
+  nerrors += Verify(__FILE__, __LINE__, "0xc.45p+8",
+                   "%a", 3141.0);
+  nerrors += Verify(__FILE__, __LINE__, "0XC.45P+8",
+                   "%A", 3141.0);
+  nerrors += Verify(__FILE__, __LINE__, "0xb.351c434a98fa8p-148",
+                   "%a", 3.141e-44);
+# endif
+  
+#endif /* TRIO_FEATURE_FLOAT */
+  
+  return nerrors;
+}
+
+/*************************************************************************
+ *
+ */
+#if TRIO_EXTENSION
+int number_writer(void *ref)
+{
+  const char *format;
+  int *data;
+
+  format = trio_get_format(ref);
+  if ((format) && trio_equal(format, "integer"))
+    {
+      data = trio_get_argument(ref);
+      if (data)
+       {
+         trio_print_int(ref, *data);
+       }
+    }
+  return 0;
+}
+
+#endif
+
+int
+VerifyFormattingUserDefined(TRIO_NOARGS)
+{
+  int nerrors = 0;
+#if TRIO_EXTENSION
+  void *number_handle;
+  int integer = 123;
+
+  number_handle = trio_register(number_writer, "number");
+
+  /* Old style */
+  nerrors += Verify(__FILE__, __LINE__, "123",
+                   "%<number:integer>", &integer);
+
+  /* New style */
+  nerrors += Verify(__FILE__, __LINE__, "123",
+                   "$<number:integer|%p>", &integer);
+  nerrors += Verify(__FILE__, __LINE__, "123",
+                   "$<integer|%p%p>", number_handle, &integer);
+  nerrors += Verify(__FILE__, __LINE__, "$<integer|123",
+                   "$<integer|%d", 123);
+  nerrors += Verify(__FILE__, __LINE__, "$integer|123>",
+                   "$integer|%d>", 123);
+
+  trio_unregister(number_handle);
+#endif
+
+  return nerrors;
+}
+
+/*************************************************************************
+ *
+ */
+int
+VerifyFormattingRegression(TRIO_NOARGS)
+{
+  int nerrors = 0;
+
+#if TRIO_FEATURE_FLOAT
+  /* 0.6 was formatted as 0.600000e+00 */
+  nerrors += Verify(__FILE__, __LINE__, "5.000000e-01",
+                   "%e", 0.5);
+  nerrors += Verify(__FILE__, __LINE__, "6.000000e-01",
+                   "%e", 0.6);
+#endif
+
+  return nerrors;
+}
+
+/*************************************************************************
+ *
+ */
+int
+VerifyFormatting(TRIO_NOARGS)
+{
+  int nerrors = 0;
+#if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_SIZE_T_UPPER
+  char buffer[256];
+#endif
+
+  nerrors += VerifyFormattingStrings();
+  nerrors += VerifyFormattingIntegers();
+  nerrors += VerifyFormattingFloats();
+  nerrors += VerifyFormattingRegression();
+  nerrors += VerifyFormattingUserDefined();
+
+  /* Pointer */
+  if (sizeof(void *) == 4)
+    {
+      nerrors += Verify(__FILE__, __LINE__, "Pointer 0x01234567",
+                       "Pointer %p", 0x1234567);
+    }
+#if defined(TRIO_COMPILER_SUPPORTS_LL)
+  else if (sizeof(void *) == 8)
+    {
+      nerrors += Verify(__FILE__, __LINE__, "Pointer 0x0123456789012345",
+                       "Pointer %p", 0x123456789012345LL);
+    }
+#endif
+  /* Nil pointer */
+  nerrors += Verify(__FILE__, __LINE__, "Pointer (nil)",
+                  "Pointer %p", NULL);
+  
   /* Char width alignment */
   nerrors += Verify(__FILE__, __LINE__, "Char X   .",
         "Char %-4c.", 'X');
@@ -495,7 +754,7 @@ VerifyFormatting(TRIO_NOARGS)
                    "%.*s", 4, "testing");
   nerrors += Verify(__FILE__, __LINE__, "testing",
                    "%.*s", -4, "testing");
-#if TRIO_UNIX98
+#if TRIO_FEATURE_POSITIONAL
   /* Positional */
   nerrors += Verify(__FILE__, __LINE__, "222 111",
                    "%2$s %1$s", "111", "222");
@@ -504,41 +763,44 @@ VerifyFormatting(TRIO_NOARGS)
                    123, 1234, 12345, 123456, 5, 6, 7, 8);
 #endif
   
-#if TRIO_GNU
+#if TRIO_FEATURE_SIZE_T_UPPER
   nerrors += Verify(__FILE__, __LINE__, "256",
                    "%Zd", sizeof(buffer));
+#endif
+
+#if TRIO_FEATURE_ERRNO
   errno = EINTR;
+# if defined(TRIO_PLATFORM_LYNX)
+#  if defined(PREDEF_STANDARD_POSIX_1996)
+  nerrors += Verify(__FILE__, __LINE__, "Interrupted system call ",
+                   "%m");
+#  else
+  nerrors += Verify(__FILE__, __LINE__, "System call interrupted",
+                   "%m");
+#  endif
+# else
   nerrors += Verify(__FILE__, __LINE__, "Interrupted system call",
                    "%m");
+# endif
 #endif
   
-#if TRIO_BSD || TRIO_GNU
+#if TRIO_FEATURE_QUAD
 # if defined(TRIO_COMPILER_SUPPORTS_LL)
   /* This may fail if the preprocessor does not recognize LL */
   nerrors += Verify(__FILE__, __LINE__, "42",
                    "%qd", 42LL);
 # endif
 #endif
-  
-#if TRIO_C99
-  nerrors += Verify(__FILE__, __LINE__, "0x2.ap+4",
-                   "%a", 42.0);
-  nerrors += Verify(__FILE__, __LINE__, "-0x2.ap+4",
-                   "%a", -42.0);
-  nerrors += Verify(__FILE__, __LINE__, "0x1.8p+0",
-                   "%a", 1.5);
-  nerrors += Verify(__FILE__, __LINE__, "0x1.6666666666666p+0",
-                   "%a", 1.4);
-  nerrors += Verify(__FILE__, __LINE__, "0xc.45p+8",
-                   "%a", 3141.0);
-  nerrors += Verify(__FILE__, __LINE__, "0XC.45P+8",
-                   "%A", 3141.0);
-  nerrors += Verify(__FILE__, __LINE__, "0xb.351c434a98fa8p-148",
-                   "%a", 3.141e-44);
+
+#if TRIO_FEATURE_SIZE_T
   nerrors += Verify(__FILE__, __LINE__, "256",
                    "%zd", sizeof(buffer));
+#endif
+#if TRIO_FEATURE_PTRDIFF_T
   nerrors += Verify(__FILE__, __LINE__, "42",
                    "%td", 42);
+#endif
+#if TRIO_FEATURE_INTMAX_T
 # if defined(TRIO_COMPILER_SUPPORTS_LL)
   /* Some compilers may not handle the LL suffix correctly */
   nerrors += Verify(__FILE__, __LINE__, "42",
@@ -546,7 +808,7 @@ VerifyFormatting(TRIO_NOARGS)
 # endif
 #endif
 
-#if TRIO_WIDECHAR
+#if TRIO_FEATURE_WIDECHAR
   nerrors += Verify(__FILE__, __LINE__, "Hello World",
                    "%ls", L"Hello World");
   nerrors += Verify(__FILE__, __LINE__, "\\aHello World",
@@ -557,7 +819,7 @@ VerifyFormatting(TRIO_NOARGS)
                    "%#lc", L'\a');
 #endif
 
-#if TRIO_MICROSOFT
+#if TRIO_FEATURE_FIXED_SIZE
   nerrors += Verify(__FILE__, __LINE__, "42",
                    "%I8d", 42);
   nerrors += Verify(__FILE__, __LINE__, "ffffffff",
@@ -594,6 +856,7 @@ VerifyFormatting(TRIO_NOARGS)
                    "Number %'d", 100);
   nerrors += Verify(__FILE__, __LINE__, "Number 1,000,000",
                    "Number %'d", 1000000);
+# if TRIO_FEATURE_FLOAT
   /* Float thousand separator */
   nerrors += Verify(__FILE__, __LINE__, "31,415.200000",
                    "%'f", 31415.2);
@@ -606,12 +869,13 @@ VerifyFormatting(TRIO_NOARGS)
                    "%.17Rf", 1.4);
   nerrors += Verify(__FILE__, __LINE__, "39413.8",
                    "%.30Rf", 39413.80);
-# if !defined(TRIO_COMPILER_ANCIENT)
+#  if !defined(TRIO_COMPILER_ANCIENT)
   /* Long double */
   nerrors += Verify(__FILE__, __LINE__, "1.4",
                    "%RLf", 1.4L);
   nerrors += Verify(__FILE__, __LINE__, "1.4",
                    "%.30RLf", 1.4L);
+#  endif
 # endif
 #endif
 
@@ -656,70 +920,124 @@ VerifyErrors(TRIO_NOARGS)
   
   /* Error: Invalid argument 1 */
   rc = trio_snprintf(buffer, sizeof(buffer), "%d %r", 42, "text");
-#if TRIO_ERRORS
+#if TRIO_FEATURE_ERRORCODE
+# if TRIO_FEATURE_STRERR
   trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d",
                TRIO_ERROR_CODE(rc),
                TRIO_ERROR_NAME(rc),
                TRIO_ERROR_POSITION(rc));
   nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 5",
                    "%s", buffer);
+# else
+  trio_snprintf(buffer, sizeof(buffer), "Err = %d, Pos = %d",
+               TRIO_ERROR_CODE(rc),
+               TRIO_ERROR_POSITION(rc));
+  nerrors += Verify(__FILE__, __LINE__, "Err = 2, Pos = 5",
+                   "%s", buffer);
+# endif
 #else
   nerrors += (rc != -1);
 #endif
+  
   /* Error: Invalid argument 2 */
   rc = trio_snprintf(buffer, sizeof(buffer), "%#");
-#if TRIO_ERRORS
+#if TRIO_FEATURE_ERRORCODE
+# if TRIO_FEATURE_STRERR
   trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d",
                TRIO_ERROR_CODE(rc),
                TRIO_ERROR_NAME(rc),
                TRIO_ERROR_POSITION(rc));
   nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 3",
                    "%s", buffer);
+# else
+  trio_snprintf(buffer, sizeof(buffer), "Err = %d, Pos = %d",
+               TRIO_ERROR_CODE(rc),
+               TRIO_ERROR_POSITION(rc));
+  nerrors += Verify(__FILE__, __LINE__, "Err = 2, Pos = 3",
+                   "%s", buffer);
+# endif
 #else
   nerrors += (rc != -1);
 #endif
+  
   /* Error: Invalid argument 3 */
   rc = trio_snprintf(buffer, sizeof(buffer), "%hhhd", 42);
-#if TRIO_ERRORS
+#if TRIO_FEATURE_ERRORCODE
+# if TRIO_FEATURE_STRERR
   trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d",
                TRIO_ERROR_CODE(rc),
                TRIO_ERROR_NAME(rc),
                TRIO_ERROR_POSITION(rc));
   nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 4",
                    "%s", buffer);
+# else
+  trio_snprintf(buffer, sizeof(buffer), "Err = %d, Pos = %d",
+               TRIO_ERROR_CODE(rc),
+               TRIO_ERROR_POSITION(rc));
+  nerrors += Verify(__FILE__, __LINE__, "Err = 2, Pos = 4",
+                   "%s", buffer);
+# endif
 #else
   nerrors += (rc != -1);
 #endif
+  
   /* Error: Double reference */
   rc = trio_snprintf(buffer, sizeof(buffer), "hello %1$d %1$d", 31, 32);
-#if TRIO_ERRORS
+#if TRIO_FEATURE_ERRORCODE
+# if TRIO_FEATURE_STRERR
   trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d",
                TRIO_ERROR_CODE(rc),
                TRIO_ERROR_NAME(rc),
                TRIO_ERROR_POSITION(rc));
-# if TRIO_UNIX98
+#  if TRIO_UNIX98
   nerrors += Verify(__FILE__, __LINE__, "Err = 4 (Double reference), Pos = 0",
                    "%s", buffer);
-# else
+#  else
   nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 9",
                    "%s", buffer);
+#  endif
+# else
+  trio_snprintf(buffer, sizeof(buffer), "Err = %d, Pos = %d",
+               TRIO_ERROR_CODE(rc),
+               TRIO_ERROR_POSITION(rc));
+#  if TRIO_UNIX98
+  nerrors += Verify(__FILE__, __LINE__, "Err = 4, Pos = 0",
+                   "%s", buffer);
+#  else
+  nerrors += Verify(__FILE__, __LINE__, "Err = 2, Pos = 9",
+                   "%s", buffer);
+#  endif
 # endif
 #else
   nerrors += (rc != -1);
 #endif
+  
   /* Error: Reference gap */
   rc = trio_snprintf(buffer, sizeof(buffer), "%3$d %1$d", 31, 32, 33);
-#if TRIO_ERRORS
+#if TRIO_FEATURE_ERRORCODE
+# if TRIO_FEATURE_STRERR
   trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d",
                TRIO_ERROR_CODE(rc),
                TRIO_ERROR_NAME(rc),
                TRIO_ERROR_POSITION(rc));
-# if TRIO_UNIX98
+#  if TRIO_UNIX98
   nerrors += Verify(__FILE__, __LINE__, "Err = 5 (Reference gap), Pos = 1",
                    "%s", buffer);
-# else
+#  else
   nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 3",
                    "%s", buffer);
+#  endif
+# else
+  trio_snprintf(buffer, sizeof(buffer), "Err = %d, Pos = %d",
+               TRIO_ERROR_CODE(rc),
+               TRIO_ERROR_POSITION(rc));
+#  if TRIO_UNIX98
+  nerrors += Verify(__FILE__, __LINE__, "Err = 5, Pos = 1",
+                   "%s", buffer);
+#  else
+  nerrors += Verify(__FILE__, __LINE__, "Err = 2, Pos = 3",
+                   "%s", buffer);
+#  endif
 # endif
 #else
   nerrors += (rc != -1);
@@ -731,6 +1049,7 @@ VerifyErrors(TRIO_NOARGS)
 /*************************************************************************
  *
  */
+#if TRIO_FEATURE_SCANF
 int
 VerifyScanningOneInteger
 TRIO_ARGS5((file, line, expected, format, original),
@@ -776,12 +1095,31 @@ VerifyScanningIntegers(TRIO_NOARGS)
 
   return nerrors;
 }
+#endif
 
 /*************************************************************************
  *
  */
+#if TRIO_FEATURE_SCANF
 int
 VerifyScanningOneFloat
+TRIO_ARGS5((file, line, expected, format, original),
+          TRIO_CONST char *file,
+          int line,
+          TRIO_CONST char *expected,
+          TRIO_CONST char *format,
+          double original)
+{
+  float number;
+  char data[512];
+  
+  trio_snprintf(data, sizeof(data), format, original);
+  trio_sscanf(data, format, &number);
+  return Verify(file, line, expected, format, number);
+}
+
+int
+VerifyScanningOneDouble
 TRIO_ARGS5((file, line, expected, format, original),
           TRIO_CONST char *file,
           int line,
@@ -802,6 +1140,7 @@ VerifyScanningFloats(TRIO_NOARGS)
 {
   int nerrors = 0;
 
+#if TRIO_FEATURE_FLOAT
   nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "42.000000",
                                      "%f", 42.0);
   nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "-42.000000",
@@ -830,29 +1169,32 @@ VerifyScanningFloats(TRIO_NOARGS)
                                      "%.6g", 1234567.0);
   nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1234567",
                                      "%.10g", 1234567.0);
-#if TRIO_C99
+# if TRIO_FEATURE_HEXFLOAT
   nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "0x2.ap+4",
                                      "%a", 42.0);
   nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "0x1.2d687p+20",
                                      "%a", 1234567.0);
   nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "0X1.2D687P+20",
                                      "%A", 1234567.0);
-#endif
-  nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.79769e+308",
-                                     "%g", 1.79769e+308);
+# endif
+  nerrors += VerifyScanningOneDouble(__FILE__, __LINE__, "1.79769e+308",
+                                     "%lg", 1.79769e+308);
   nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "nan",
                                      "%f", trio_nan());
   nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "NAN",
                                      "%F", trio_nan());
   nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "-inf",
                                      "%f", trio_ninf());
+#endif
   
   return nerrors;
 }
+#endif
 
 /*************************************************************************
  *
  */
+#if TRIO_FEATURE_SCANF
 int
 VerifyScanningOneString
 TRIO_ARGS5((file, line, expected, format, original),
@@ -866,6 +1208,7 @@ TRIO_ARGS5((file, line, expected, format, original),
   char data[512];
   
   trio_snprintf(data, sizeof(data), "%s", original);
+  string[0] = 0;
   trio_sscanf(data, format, string);
   return Verify(file, line, expected, "%s", string);
 }
@@ -875,6 +1218,10 @@ VerifyScanningStrings(TRIO_NOARGS)
 {
   int nerrors = 0;
 
+  nerrors += VerifyScanningOneString(__FILE__, __LINE__, "",
+                                    "hello", "hello");
+  nerrors += VerifyScanningOneString(__FILE__, __LINE__, "",
+                                    "", "");
   nerrors += VerifyScanningOneString(__FILE__, __LINE__, "hello",
                                     "%s", "hello");
   nerrors += VerifyScanningOneString(__FILE__, __LINE__, "hello",
@@ -902,25 +1249,35 @@ VerifyScanningStrings(TRIO_NOARGS)
 
   return nerrors;
 }
+#endif
 
 /*************************************************************************
  *
  */
+#if TRIO_FEATURE_SCANF
 int
 VerifyScanningRegression(TRIO_NOARGS)
 {
   int nerrors = 0;
   int rc;
-  int index;
+#if TRIO_FEATURE_FLOAT
+  int offset;
   double dnumber;
+# if defined(TRIO_BREESE)
   trio_long_double_t ldnumber;
+# endif
+#endif
   long lnumber;
   int number;
   char ch;
+  char buffer[4096];
+  FILE *stream;
 
-  rc = trio_sscanf("1.5", "%lf%n", &dnumber, &index);
+#if TRIO_FEATURE_FLOAT
+  rc = trio_sscanf("1.5", "%lf%n", &dnumber, &offset);
   nerrors += Verify(__FILE__, __LINE__, "1 3 1.500000",
-                   "%d %d %f", rc, index, dnumber);
+                   "%d %d %f", rc, offset, dnumber);
+#endif
   rc = trio_sscanf("q 123", "%c%ld", &ch, &lnumber);
   nerrors += Verify(__FILE__, __LINE__, "q 123",
                    "%c %ld", ch, lnumber);
@@ -930,20 +1287,87 @@ VerifyScanningRegression(TRIO_NOARGS)
   rc = trio_sscanf("abc def", "%*s%n", &number);
   nerrors += Verify(__FILE__, __LINE__, "0 3",
                    "%d %d", rc, number);
+#if TRIO_FEATURE_FLOAT
   rc = trio_sscanf("0.141882295971771490", "%lf", &dnumber);
+  /* FIXME: Verify */
+#endif
   number = 33;
   rc = trio_sscanf("total 1", "total %d", &number);
   nerrors += Verify(__FILE__, __LINE__, "1 1",
                    "%d %d", rc, number);
 #if defined(TRIO_BREESE)
+# if TRIO_FEATURE_FLOAT
   nerrors += Verify(__FILE__, __LINE__, "1 0.141882295971771488",
                    "%d %.18f", rc, dnumber);
   rc = trio_sscanf("0.141882295971771490", "%Lf", &ldnumber);
   nerrors += Verify(__FILE__, __LINE__, "1 0.141882295971771490",
                    "%d %.18Lf", rc, ldnumber);
+# endif
+#endif
+#if TRIO_FEATURE_FLOAT
+  rc = trio_sscanf("1.e-6", "%lg", &dnumber);
+  nerrors += Verify(__FILE__, __LINE__, "1e-06",
+                   "%g", dnumber);
+  rc = trio_sscanf("1e-6", "%lg", &dnumber);
+  nerrors += Verify(__FILE__, __LINE__, "1e-06",
+                   "%g", dnumber);
 #endif
+
+  /* Do not overwrite result on matching error */
+  ch = 'a';
+  rc = trio_sscanf("0123456789", "%1[c]", &ch);
+  nerrors += Verify(__FILE__, __LINE__, "a",
+                   "%c", ch);
+
+  /* Scan plus prefix for unsigned integer */
+  rc = trio_sscanf("+42", "%u", &number);
+  nerrors += Verify(__FILE__, __LINE__, "1 42",
+                   "%d %u", rc, number);
+
+  /* Scan minus prefix even for unsigned integer */
+  rc = trio_sscanf("-42", "%u", &number);
+  sprintf(buffer, "1 %u", -42U);
+  nerrors += Verify(__FILE__, __LINE__, buffer,
+                   "%d %u", rc, number);
+
+  /* A scangroup match failure should not bind its argument,
+   * i.e., it shouldn't match the empty string. */
+  sprintf(buffer, "SPQR");
+  rc = trio_sscanf("asdf", "%[c]", buffer);
+  nerrors += Verify(__FILE__, __LINE__, "0 SPQR",
+                   "%d %s", rc, buffer);
+
+  /* Even whitespace scanning shouldn't try to read past EOF */
+  stream = tmpfile();
+  trio_fprintf(stream, "");
+  rewind(stream);
+  rc = trio_fscanf(stream, " ");
+  nerrors += Verify(__FILE__, __LINE__, "0",
+                   "%d", rc);
+  fclose(stream);
+
+  /* Idem, after a succesfull read */
+  stream = tmpfile();
+  trio_fprintf(stream, "123");
+  rewind(stream);
+  rc = trio_fscanf(stream, "%i ", &number);
+  nerrors += Verify(__FILE__, __LINE__, "1 123",
+                   "%d %i", rc, number);
+  fclose(stream);
+
+  /* The scanner should unget its read-ahead char */
+  stream = tmpfile();
+  trio_fprintf(stream, "123");
+  rewind(stream);
+  trio_fscanf(stream, "%*c");
+  trio_fscanf(stream, "%c", &ch);
+  nerrors += Verify(__FILE__, __LINE__, "2",
+                   "%c", ch);
+  fclose(stream);
+
   return nerrors;
 }
+#endif
 
 /*************************************************************************
  *
@@ -952,12 +1376,12 @@ int
 VerifyScanning(TRIO_NOARGS)
 {
   int nerrors = 0;
-
+#if TRIO_FEATURE_SCANF
   nerrors += VerifyScanningIntegers();
   nerrors += VerifyScanningFloats();
   nerrors += VerifyScanningStrings();
   nerrors += VerifyScanningRegression();
-  
+#endif
   return nerrors;
 }
 
@@ -970,8 +1394,10 @@ VerifyStrings(TRIO_NOARGS)
   int nerrors = 0;
 #if !defined(TRIO_MINIMAL)
   char buffer[512];
+#if TRIO_FEATURE_FLOAT
   double dnumber;
   float fnumber;
+#endif
   char *end;
 
   /* Comparison */
@@ -1065,6 +1491,7 @@ VerifyStrings(TRIO_NOARGS)
     Report0(__FILE__, __LINE__);
   }
 
+#if TRIO_FEATURE_FLOAT
   /* Double conversion */
   trio_copy(buffer, "3.1415");
   dnumber = trio_to_double(buffer, NULL);
@@ -1077,6 +1504,7 @@ VerifyStrings(TRIO_NOARGS)
     nerrors++;
     Report0(__FILE__, __LINE__);
   }
+#endif
 
   /* Long conversion */
   trio_copy(buffer, "3.1415");
@@ -1107,6 +1535,7 @@ VerifyDynamicStrings(TRIO_NOARGS)
   int nerrors = 0;
 #if !defined(TRIO_MINIMAL)
   trio_string_t *string;
+  const char no_terminate[5] = { 'h', 'e', 'l', 'l', 'o' };
 
   string = trio_xstring_duplicate("Find me now");
   if (string == NULL) {
@@ -1126,6 +1555,9 @@ VerifyDynamicStrings(TRIO_NOARGS)
     nerrors++;
   if (trio_xstring_match_case(string, "* ME *"))
     nerrors++;
+  if (!trio_xstring_append_max(string, no_terminate, 5) ||
+      !trio_xstring_equal(string, "FIND ME NOW AND AGAINhello"))
+    nerrors++;
   
  error:
   if (string)
@@ -1170,10 +1602,12 @@ main(TRIO_NOARGS)
 
   printf("%s\n", rcsid);
 
+#if TRIO_EXTENSION
   /* Override system locale settings */
   trio_locale_set_decimal_point(".");
   trio_locale_set_thousand_separator(",");
   trio_locale_set_grouping("\3");
+#endif
 
   printf("Verifying strings\n");
   nerrors += VerifyStrings();
@@ -1198,7 +1632,7 @@ main(TRIO_NOARGS)
   nerrors += VerifyAllocate();
 
   if (nerrors == 0)
-    printf("Regression test suceeded\n");
+    printf("Regression test succeeded\n");
   else
     printf("Regression test failed in %d instance(s)\n", nerrors);