/************************************************************************* * Regression test */ #include "triodef.h" #if defined(TRIO_COMPILER_ANCIENT) # include #else # include #endif #include #include #include #include #include "trio.h" #include "triop.h" #include "trionan.h" #if defined(TRIO_MINIMAL) # define TRIO_STRING_PUBLIC static # include "triostr.c" #else # include "triostr.h" #endif #undef printf #if TRIO_WIDECHAR # include #endif #define QUOTE(x) #x #define DOUBLE_EQUAL(x,y) (((x)>(y)-DBL_EPSILON) && ((x)<(y)+DBL_EPSILON)) #define FLOAT_EQUAL(x,y) (((x)>(y)-FLT_EPSILON) && ((x)<(y)+FLT_EPSILON)) static TRIO_CONST char rcsid[] = "@(#)$Id: regression.c,v 1.44 2002/12/29 15:08:56 breese Exp $"; /************************************************************************* * */ static void Dump TRIO_ARGS2((buffer, rc), char *buffer, int rc) { if (rc < 0) { printf("Err = %d (%s), Pos = %d\n", TRIO_ERROR_CODE(rc), TRIO_ERROR_NAME(rc), TRIO_ERROR_POSITION(rc)); } else if (buffer) printf("buffer[% 3d] = \"%s\"\n", rc, buffer); } /************************************************************************* * */ static void Report0 TRIO_ARGS2((file, line), TRIO_CONST char *file, int line) { printf("Verification failed in %s:%d.\n", file, line); } /************************************************************************* * */ static void Report TRIO_ARGS4((file, line, expected, got), TRIO_CONST char *file, int line, TRIO_CONST char *expected, TRIO_CONST char *got) { Report0(file, line); printf(" Expected \"%s\"\n", expected); printf(" Got \"%s\"\n", got); } /************************************************************************* * */ int Verify TRIO_VARGS5((file, line, result, fmt, va_alist), TRIO_CONST char *file, int line, TRIO_CONST char *result, TRIO_CONST char *fmt, TRIO_VA_DECL) { int rc; va_list args; char buffer[4096]; TRIO_VA_START(args, fmt); rc = trio_vsnprintf(buffer, sizeof(buffer), fmt, args); if (rc < 0) Dump(buffer, rc); TRIO_VA_END(args); if (!trio_equal_case(result, buffer)) { Report(file, line, result, buffer); return 1; } return 0; } /************************************************************************* * */ int VerifyReturnValues(TRIO_NOARGS) { int nerrors = 0; int rc; int count; char *expected; char buffer[4096]; char result[4096]; rc = trio_sprintf(buffer, "%s%n", "0123456789", &count); trio_sprintf(result, "%d %d %s", rc, count, buffer); expected = "10 10 0123456789"; if (!trio_equal_case(result, expected)) { nerrors++; Report(__FILE__, __LINE__, expected, result); } rc = trio_snprintf(buffer, sizeof(buffer), "%s%n", "0123456789", &count); trio_sprintf(result, "%d %d %s", rc, count, buffer); expected = "10 10 0123456789"; if (!trio_equal_case(result, expected)) { nerrors++; Report(__FILE__, __LINE__, expected, result); } rc = trio_snprintf(buffer, 4, "%s%n", "0123456789", &count); trio_sprintf(result, "%d %d %s", rc, count, buffer); expected = "10 3 012"; if (!trio_equal_case(result, expected)) { nerrors++; Report(__FILE__, __LINE__, expected, result); } /* The output buffer contains the empty string */ rc = trio_snprintf(buffer, 1, "%s%n", "0123456789", &count); trio_sprintf(result, "%d %d %s", rc, count, buffer); expected = "10 0 "; if (!trio_equal_case(result, expected)) { nerrors++; Report(__FILE__, __LINE__, expected, result); } /* The output buffer should be left untouched when max size is 0 */ trio_sprintf(buffer, "DO NOT TOUCH"); rc = trio_snprintf(buffer, 0, "%s%n", "0123456789", &count); trio_sprintf(result, "%d %d %s", rc, count, buffer); expected = "10 0 DO NOT TOUCH"; if (!trio_equal_case(result, expected)) { nerrors++; Report(__FILE__, __LINE__, expected, result); } return nerrors; } /************************************************************************* * */ #define TEST_STRING "0123456789" int VerifyAllocate(TRIO_NOARGS) { int nerrors = 0; int rc; char *string; int count; int test_size = sizeof(TEST_STRING) - 1; /* Allocate a string with the result */ rc = trio_asprintf(&string, "%s%n", TEST_STRING, &count); if (rc < 0) { nerrors++; Dump(string, rc); } else if (count != test_size) { nerrors++; printf("Validation failed in %s:%d\n", __FILE__, __LINE__); printf(" Expected %%n = %d\n", test_size); printf(" Got %%n = %d\n", count); } else if (!trio_equal_case(string, TEST_STRING)) { nerrors++; Report(__FILE__, __LINE__, TEST_STRING, string); } if (string) free(string); return nerrors; } /************************************************************************* * */ int VerifyFormatting(TRIO_NOARGS) { int nerrors = 0; char buffer[256]; /* Normal text */ nerrors += Verify(__FILE__, __LINE__, "Hello world", "Hello world"); /* String */ nerrors += Verify(__FILE__, __LINE__, "Hello world", "%s", "Hello world"); /* Pointer */ if (sizeof(void *) == 4) { nerrors += Verify(__FILE__, __LINE__, "Pointer 0x01234567", "Pointer %p", 0x1234567); } else if (sizeof(void *) == 8) { nerrors += Verify(__FILE__, __LINE__, "Pointer 0x0123456789012345", "Pointer %p", 0x123456789012345); } /* Nil pointer */ nerrors += Verify(__FILE__, __LINE__, "Pointer (nil)", "Pointer %p", NULL); /* Integer */ nerrors += Verify(__FILE__, __LINE__, "Number 42", "Number %d", 42); nerrors += Verify(__FILE__, __LINE__, "Number -42", "Number %d", -42); nerrors += Verify(__FILE__, __LINE__, "Number 42", "Number %ld", 42L); nerrors += Verify(__FILE__, __LINE__, "Number -42", "Number %ld", -42L); /* Integer width */ nerrors += Verify(__FILE__, __LINE__, " 1234", "%6d", 1234); nerrors += Verify(__FILE__, __LINE__, " 1234", "%*d", 6, 1234); /* Integer width overrun */ nerrors += Verify(__FILE__, __LINE__, "123456", "%4d", 123456); /* Integer precision */ nerrors += Verify(__FILE__, __LINE__, "0012", "%.4d", 12); nerrors += Verify(__FILE__, __LINE__, "0012", "%.*d", 4, 12); nerrors += Verify(__FILE__, __LINE__, " 0012", "%6.*d", 4, 12); nerrors += Verify(__FILE__, __LINE__, " 0012", "%*.*d", 6, 4, 12); nerrors += Verify(__FILE__, __LINE__, " 0012", "%*.*.*d", 6, 4, 2, 12); nerrors += Verify(__FILE__, __LINE__, " 0012", "%*.*.*i", 6, 4, 10, 12); /* Integer sign, zero-padding, and width */ nerrors += Verify(__FILE__, __LINE__, "+01234", "%+06d", 1234); nerrors += Verify(__FILE__, __LINE__, " 01234", "% 06d", 1234); nerrors += Verify(__FILE__, __LINE__, "+01234", "% +06d", 1234); /* Integer adjust, zero-padding, and width */ nerrors += Verify(__FILE__, __LINE__, "12 ", "%-08d", 12); /* Integer zero-padding, width, and precision */ nerrors += Verify(__FILE__, __LINE__, " 000012", "%08.6d", 12); /* Integer base */ nerrors += Verify(__FILE__, __LINE__, "42", "%u", 42); nerrors += Verify(__FILE__, __LINE__, "-1", "%d", -1); nerrors += Verify(__FILE__, __LINE__, "52", "%o", 42); nerrors += Verify(__FILE__, __LINE__, "052", "%#o", 42); nerrors += Verify(__FILE__, __LINE__, "0", "%#o", 0); nerrors += Verify(__FILE__, __LINE__, "2a", "%x", 42); nerrors += Verify(__FILE__, __LINE__, "2A", "%X", 42); nerrors += Verify(__FILE__, __LINE__, "0x2a", "%#x", 42); nerrors += Verify(__FILE__, __LINE__, "0X2A", "%#X", 42); nerrors += Verify(__FILE__, __LINE__, "0x00c ", "%-#6.3x", 12); nerrors += Verify(__FILE__, __LINE__, "", "%.d", 0); nerrors += Verify(__FILE__, __LINE__, "", "%#.d", 0); nerrors += Verify(__FILE__, __LINE__, "42", "%.d", 42); nerrors += Verify(__FILE__, __LINE__, "", "%.o", 0); nerrors += Verify(__FILE__, __LINE__, " 0000", "%8.4o", 0); nerrors += Verify(__FILE__, __LINE__, " 0", "%8o", 0); nerrors += Verify(__FILE__, __LINE__, "00000000", "%08o", 0); nerrors += Verify(__FILE__, __LINE__, "0", "%#.o", 0); nerrors += Verify(__FILE__, __LINE__, "52", "%.o", 42); nerrors += Verify(__FILE__, __LINE__, "", "%.x", 0); nerrors += Verify(__FILE__, __LINE__, "", "%#.x", 0); nerrors += Verify(__FILE__, __LINE__, "2a", "%.x", 42); sprintf(buffer, "%u", UINT_MAX); nerrors += Verify(__FILE__, __LINE__, buffer, "%u", -1); sprintf(buffer, "%x", UINT_MAX); nerrors += Verify(__FILE__, __LINE__, buffer, "%x", -1); /* Double */ nerrors += Verify(__FILE__, __LINE__, "3141.000000", "%f", 3141.0); nerrors += Verify(__FILE__, __LINE__, "3141.500000", "%f", 3141.5); nerrors += Verify(__FILE__, __LINE__, "3.141000e+03", "%e", 3141.0); nerrors += Verify(__FILE__, __LINE__, " -2.3420e-02", "%16.4e", -2.342E-02); nerrors += Verify(__FILE__, __LINE__, " -2.3420e-22", "%16.4e", -2.342E-22); nerrors += Verify(__FILE__, __LINE__, " 2.3420e-02", "% 16.4e", 2.342E-02); nerrors += Verify(__FILE__, __LINE__, " 2.3420e-02", "% 1.4e", 2.342E-02); nerrors += Verify(__FILE__, __LINE__, "3.141000E-44", "%E", 3.141e-44); nerrors += Verify(__FILE__, __LINE__, "0", "%g", 0.0); nerrors += Verify(__FILE__, __LINE__, "-0", "%g", trio_nzero()); nerrors += Verify(__FILE__, __LINE__, "3141.5", "%g", 3141.5); nerrors += Verify(__FILE__, __LINE__, "3.1415E-06", "%G", 3.1415e-6); nerrors += Verify(__FILE__, __LINE__, "+3141.000000", "%+f", 3141.0); nerrors += Verify(__FILE__, __LINE__, "-3141.000000", "%+f", -3141.0); nerrors += Verify(__FILE__, __LINE__, "0.333333", "%f", 1.0/3.0); nerrors += Verify(__FILE__, __LINE__, "0.666667", "%f", 2.0/3.0); /* Beyond accuracy */ nerrors += Verify(__FILE__, __LINE__, "0.000000", "%f", 1.234567890123456789e-20); #if defined(TRIO_BREESE) nerrors += Verify(__FILE__, __LINE__, "1.3999999999999999111821580299875", "%.32g", 1.4); nerrors += Verify(__FILE__, __LINE__, "1.39999999999999991118215802998748", "%.32f", 1.4); nerrors += Verify(__FILE__, __LINE__, "1.3999999999999999111821580300", "%.28f", 1.4); nerrors += Verify(__FILE__, __LINE__, "1.399999999999999911182158", "%.24f", 1.4); nerrors += Verify(__FILE__, __LINE__, "1.39999999999999991", "%.17f", 1.4); nerrors += Verify(__FILE__, __LINE__, "1.40000000000000", "%.14f", 1.4); nerrors += Verify(__FILE__, __LINE__, "39413.800000000002910383045673370361", "%.30f", 39413.80); #endif /* 2^-1 + 2^-15 */ nerrors += Verify(__FILE__, __LINE__, "0.500030517578125", "%.*g", DBL_DIG + 10, 0.500030517578125); /* Double decimal point */ nerrors += Verify(__FILE__, __LINE__, "3141", "%.0f", 3141.0); nerrors += Verify(__FILE__, __LINE__, "3142", "%.0f", 3141.5); nerrors += Verify(__FILE__, __LINE__, "3141", "%.f", 3141.0); nerrors += Verify(__FILE__, __LINE__, "12", "%.f", 12.34); nerrors += Verify(__FILE__, __LINE__, "3141.000", "%.3f", 3141.0); nerrors += Verify(__FILE__, __LINE__, "3141.000000", "%#f", 3141.0); nerrors += Verify(__FILE__, __LINE__, "0.0000", "%#.4f", 0.0); nerrors += Verify(__FILE__, __LINE__, "0.000", "%#.4g", 0.0); nerrors += Verify(__FILE__, __LINE__, "3141.0000", "%#.4f", 3141.0); nerrors += Verify(__FILE__, __LINE__, "3141.", "%#.0f", 3141.0); nerrors += Verify(__FILE__, __LINE__, "3141.", "%#.f", 3141.0); nerrors += Verify(__FILE__, __LINE__, "11.0000", "%#.4f", 11.0); nerrors += Verify(__FILE__, __LINE__, "100.00", "%.2f", 99.9999); nerrors += Verify(__FILE__, __LINE__, "3e+03", "%.e", 3141.0); nerrors += Verify(__FILE__, __LINE__, "3.e+03", "%#.e", 3141.0); nerrors += Verify(__FILE__, __LINE__, "100", "%.2g", 99.9999); nerrors += Verify(__FILE__, __LINE__, "100.", "%#.2g", 99.9999); nerrors += Verify(__FILE__, __LINE__, "0.123", "%0g", 0.123); nerrors += Verify(__FILE__, __LINE__, "1.00e+00", "%.2e", 0.9999); nerrors += Verify(__FILE__, __LINE__, "1", "%.2g", 0.9999); nerrors += Verify(__FILE__, __LINE__, "2", "%.g", 1.5); nerrors += Verify(__FILE__, __LINE__, "0.01", "%.2g", 0.01); nerrors += Verify(__FILE__, __LINE__, "0.010", "%#.2g", 0.01); /* Double width, precision, and zero padding */ nerrors += Verify(__FILE__, __LINE__, "00003.141500e+03", "%016e", 3141.5); nerrors += Verify(__FILE__, __LINE__, " 3.141500e+03", "%16e", 3141.5); nerrors += Verify(__FILE__, __LINE__, "3.141500e+03 ", "%-16e", 3141.5); nerrors += Verify(__FILE__, __LINE__, "03.142e+03", "%010.3e", 3141.5); #if !defined(TRIO_COMPILER_ANCIENT) /* Long double */ nerrors += Verify(__FILE__, __LINE__, "1.400000", "%Lf", 1.4L); #endif /* Special cases */ nerrors += Verify(__FILE__, __LINE__, "1.00", "%.2f", 0.999); nerrors += Verify(__FILE__, __LINE__, "100", "%.0f", 99.9); nerrors += Verify(__FILE__, __LINE__, "inf", "%f", trio_pinf()); nerrors += Verify(__FILE__, __LINE__, "-inf", "%f", trio_ninf()); nerrors += Verify(__FILE__, __LINE__, "INF", "%F", trio_pinf()); nerrors += Verify(__FILE__, __LINE__, "-INF", "%F", trio_ninf()); /* May fail if NaN is unsupported */ nerrors += Verify(__FILE__, __LINE__, "nan", "%f", trio_nan()); nerrors += Verify(__FILE__, __LINE__, "NAN", "%F", trio_nan()); /* Char width alignment */ nerrors += Verify(__FILE__, __LINE__, "Char X .", "Char %-4c.", 'X'); /* String width / precision */ nerrors += Verify(__FILE__, __LINE__, " testing", "%8s", "testing"); nerrors += Verify(__FILE__, __LINE__, "testing ", "%-8s", "testing"); nerrors += Verify(__FILE__, __LINE__, " testing", "%*s", 8, "testing"); nerrors += Verify(__FILE__, __LINE__, "testing ", "%*s", -8, "testing"); nerrors += Verify(__FILE__, __LINE__, "test", "%.4s", "testing"); nerrors += Verify(__FILE__, __LINE__, "test", "%.*s", 4, "testing"); nerrors += Verify(__FILE__, __LINE__, "testing", "%.*s", -4, "testing"); #if TRIO_UNIX98 /* Positional */ nerrors += Verify(__FILE__, __LINE__, "222 111", "%2$s %1$s", "111", "222"); nerrors += Verify(__FILE__, __LINE__, "123456 12345 0001234 00123", "%4$d %3$*8$d %2$.*7$d %1$*6$.*5$d", 123, 1234, 12345, 123456, 5, 6, 7, 8); #endif #if TRIO_GNU nerrors += Verify(__FILE__, __LINE__, "256", "%Zd", sizeof(buffer)); errno = EINTR; nerrors += Verify(__FILE__, __LINE__, "Interrupted system call", "%m"); #endif #if TRIO_BSD || TRIO_GNU # if defined(TRIO_COMPILER_SUPPORTS_LL) /* This may fail if the preprocessor does not recognize LL */ nerrors += Verify(__FILE__, __LINE__, "42", "%qd", 42LL); # endif #endif #if TRIO_C99 nerrors += Verify(__FILE__, __LINE__, "0x2.ap+4", "%a", 42.0); nerrors += Verify(__FILE__, __LINE__, "-0x2.ap+4", "%a", -42.0); nerrors += Verify(__FILE__, __LINE__, "0x1.8p+0", "%a", 1.5); nerrors += Verify(__FILE__, __LINE__, "0x1.6666666666666p+0", "%a", 1.4); nerrors += Verify(__FILE__, __LINE__, "0xc.45p+8", "%a", 3141.0); nerrors += Verify(__FILE__, __LINE__, "0XC.45P+8", "%A", 3141.0); nerrors += Verify(__FILE__, __LINE__, "0xb.351c434a98fa8p-148", "%a", 3.141e-44); nerrors += Verify(__FILE__, __LINE__, "256", "%zd", sizeof(buffer)); nerrors += Verify(__FILE__, __LINE__, "42", "%td", 42); # if defined(TRIO_COMPILER_SUPPORTS_LL) /* Some compilers may not handle the LL suffix correctly */ nerrors += Verify(__FILE__, __LINE__, "42", "%jd", 42LL); # endif #endif #if TRIO_WIDECHAR nerrors += Verify(__FILE__, __LINE__, "Hello World", "%ls", L"Hello World"); nerrors += Verify(__FILE__, __LINE__, "\\aHello World", "%#ls", L"\aHello World"); nerrors += Verify(__FILE__, __LINE__, "A", "%lc", L'A'); nerrors += Verify(__FILE__, __LINE__, "\\a", "%#lc", L'\a'); #endif #if TRIO_MICROSOFT nerrors += Verify(__FILE__, __LINE__, "42", "%I8d", 42); nerrors += Verify(__FILE__, __LINE__, "ffffffff", "%I16x", -1); #endif #if TRIO_EXTENSION nerrors += Verify(__FILE__, __LINE__, " 42 86", "%!4d %d", 42, 86); nerrors += Verify(__FILE__, __LINE__, "0042 0086", "%!04d %d", 42, 86); nerrors += Verify(__FILE__, __LINE__, "42", "%&d", sizeof(long), 42L); /* Non-printable string */ nerrors += Verify(__FILE__, __LINE__, "NonPrintable \\x01 \\a \\\\", "NonPrintable %#s", "\01 \07 \\"); nerrors += Verify(__FILE__, __LINE__, "\\a \\b \\t \\n \\v \\f \\r", "%#s", "\007 \010 \011 \012 \013 \014 \015"); /* Quote flag */ nerrors += Verify(__FILE__, __LINE__, "Another \"quoted\" string", "Another %'s string", "quoted"); /* Integer base */ nerrors += Verify(__FILE__, __LINE__, "Number 42 == 1120 (base 3)", "Number %d == %..3i (base 3)", 42, 42); /* Integer base (specifier base must be used instead of base modifier) */ nerrors += Verify(__FILE__, __LINE__, "42", "%..3d", 42); nerrors += Verify(__FILE__, __LINE__, "52", "%..3o", 42); nerrors += Verify(__FILE__, __LINE__, "2a", "%..3x", 42); /* Integer thousand separator */ nerrors += Verify(__FILE__, __LINE__, "Number 100", "Number %'d", 100); nerrors += Verify(__FILE__, __LINE__, "Number 1,000,000", "Number %'d", 1000000); /* Float thousand separator */ nerrors += Verify(__FILE__, __LINE__, "31,415.200000", "%'f", 31415.2); nerrors += Verify(__FILE__, __LINE__, "1,000,000.000000", "%'f", 1000000.0); /* Rounding modifier */ nerrors += Verify(__FILE__, __LINE__, "1.4", "%.32Rf", 1.4); nerrors += Verify(__FILE__, __LINE__, "1.4", "%.17Rf", 1.4); nerrors += Verify(__FILE__, __LINE__, "39413.8", "%.30Rf", 39413.80); # if !defined(TRIO_COMPILER_ANCIENT) /* Long double */ nerrors += Verify(__FILE__, __LINE__, "1.4", "%RLf", 1.4L); nerrors += Verify(__FILE__, __LINE__, "1.4", "%.30RLf", 1.4L); # endif #endif #if defined(TRIO_BREESE) /* * These results depends on issues beyond our control. For example, * the accuracy of floating-point numbers depends on the underlying * floating-point hardware (e.g. whether IEEE 754 double or extended- * double format is used). * * These tests are therefore not part of the normal regression test, * but we keep them here for development purposes. */ nerrors += Verify(__FILE__, __LINE__, "123456789012345680868.000000", "%f", 1.234567890123456789e20); nerrors += Verify(__FILE__, __LINE__, "1.23456789012345677901e-20", "%.20e", 1.2345678901234567e-20); nerrors += Verify(__FILE__, __LINE__, "0.666666666666666629659233", "%.*g", DBL_DIG + 10, 2.0/3.0); nerrors += Verify(__FILE__, __LINE__, "123456789012345700000", "%Rf", 1.234567890123456789e20); # if !defined(TRIO_COMPILER_ANCIENT) nerrors += Verify(__FILE__, __LINE__, "0.666666666666666667", "%RLf", (2.0L/3.0L)); nerrors += Verify(__FILE__, __LINE__, "0.666666666666666667", "%.30RLf", (2.0L/3.0L)); # endif #endif return nerrors; } /************************************************************************* * */ int VerifyErrors(TRIO_NOARGS) { char buffer[512]; int rc; int nerrors = 0; /* Error: Invalid argument 1 */ rc = trio_snprintf(buffer, sizeof(buffer), "%d %r", 42, "text"); #if TRIO_ERRORS trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d", TRIO_ERROR_CODE(rc), TRIO_ERROR_NAME(rc), TRIO_ERROR_POSITION(rc)); nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 5", "%s", buffer); #else nerrors += (rc != -1); #endif /* Error: Invalid argument 2 */ rc = trio_snprintf(buffer, sizeof(buffer), "%#"); #if TRIO_ERRORS trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d", TRIO_ERROR_CODE(rc), TRIO_ERROR_NAME(rc), TRIO_ERROR_POSITION(rc)); nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 3", "%s", buffer); #else nerrors += (rc != -1); #endif /* Error: Invalid argument 3 */ rc = trio_snprintf(buffer, sizeof(buffer), "%hhhd", 42); #if TRIO_ERRORS trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d", TRIO_ERROR_CODE(rc), TRIO_ERROR_NAME(rc), TRIO_ERROR_POSITION(rc)); nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 4", "%s", buffer); #else nerrors += (rc != -1); #endif /* Error: Double reference */ rc = trio_snprintf(buffer, sizeof(buffer), "hello %1$d %1$d", 31, 32); #if TRIO_ERRORS trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d", TRIO_ERROR_CODE(rc), TRIO_ERROR_NAME(rc), TRIO_ERROR_POSITION(rc)); # if TRIO_UNIX98 nerrors += Verify(__FILE__, __LINE__, "Err = 4 (Double reference), Pos = 0", "%s", buffer); # else nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 9", "%s", buffer); # endif #else nerrors += (rc != -1); #endif /* Error: Reference gap */ rc = trio_snprintf(buffer, sizeof(buffer), "%3$d %1$d", 31, 32, 33); #if TRIO_ERRORS trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d", TRIO_ERROR_CODE(rc), TRIO_ERROR_NAME(rc), TRIO_ERROR_POSITION(rc)); # if TRIO_UNIX98 nerrors += Verify(__FILE__, __LINE__, "Err = 5 (Reference gap), Pos = 1", "%s", buffer); # else nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 3", "%s", buffer); # endif #else nerrors += (rc != -1); #endif return nerrors; } /************************************************************************* * */ int VerifyScanningOneInteger TRIO_ARGS5((file, line, expected, format, original), TRIO_CONST char *file, int line, TRIO_CONST char *expected, TRIO_CONST char *format, int original) { int number; char data[512]; trio_snprintf(data, sizeof(data), format, original); trio_sscanf(data, format, &number); return Verify(file, line, expected, format, number); } int VerifyScanningIntegers(TRIO_NOARGS) { int nerrors = 0; nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "42", "%i", 42); nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "42", "%d", 42); nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "-42", "%d", -42); nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "2147483647", "%d", 2147483647); nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "42", "%u", 42); nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "2a", "%x", 42); nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "52", "%o", 42); nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "101010", "%..2i", 42); nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "0x2a", "%#x", 42); nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "052", "%#o", 42); return nerrors; } /************************************************************************* * */ int VerifyScanningOneFloat TRIO_ARGS5((file, line, expected, format, original), TRIO_CONST char *file, int line, TRIO_CONST char *expected, TRIO_CONST char *format, double original) { double number; char data[512]; trio_snprintf(data, sizeof(data), format, original); trio_sscanf(data, format, &number); return Verify(file, line, expected, format, number); } int VerifyScanningFloats(TRIO_NOARGS) { int nerrors = 0; nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "42.000000", "%f", 42.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "-42.000000", "%f", -42.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "4.200000e+01", "%e", 42.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "4.200000E+01", "%E", 42.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "42", "%g", 42.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.23457e+06", "%g", 1234567.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.23457e-06", "%g", 1.234567e-6); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.23457E+06", "%G", 1234567.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.234567e+06", "%12e", 1234567.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.234500e+00", "%6e", 1234567.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.234567e+06", "%.6e", 1234567.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.2345670000e+06", "%.10e", 1234567.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.23457e+06", "%.6g", 1234567.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1234567", "%.10g", 1234567.0); #if TRIO_C99 nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "0x2.ap+4", "%a", 42.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "0x1.2d687p+20", "%a", 1234567.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "0X1.2D687P+20", "%A", 1234567.0); #endif nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.79769e+308", "%g", 1.79769e+308); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "nan", "%f", trio_nan()); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "NAN", "%F", trio_nan()); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "-inf", "%f", trio_ninf()); return nerrors; } /************************************************************************* * */ int VerifyScanningOneString TRIO_ARGS5((file, line, expected, format, original), TRIO_CONST char *file, int line, TRIO_CONST char *expected, TRIO_CONST char *format, char *original) { char string[512]; char data[512]; trio_snprintf(data, sizeof(data), "%s", original); trio_sscanf(data, format, string); return Verify(file, line, expected, "%s", string); } int VerifyScanningStrings(TRIO_NOARGS) { int nerrors = 0; nerrors += VerifyScanningOneString(__FILE__, __LINE__, "hello", "%s", "hello"); nerrors += VerifyScanningOneString(__FILE__, __LINE__, "hello", "%s", "hello world"); nerrors += VerifyScanningOneString(__FILE__, __LINE__, "hello world", "%[^\n]", "hello world"); nerrors += VerifyScanningOneString(__FILE__, __LINE__, "(nil)", "%s", NULL); nerrors += VerifyScanningOneString(__FILE__, __LINE__, "hello", "%20s", "hello"); nerrors += VerifyScanningOneString(__FILE__, __LINE__, "he", "%2s", "hello"); nerrors += VerifyScanningOneString(__FILE__, __LINE__, "ab", "%[ab]", "abcba"); nerrors += VerifyScanningOneString(__FILE__, __LINE__, "abcba", "%[abc]", "abcba"); nerrors += VerifyScanningOneString(__FILE__, __LINE__, "abcba", "%[a-c]", "abcba"); #if TRIO_EXTENSION nerrors += VerifyScanningOneString(__FILE__, __LINE__, "abcba", "%[[:alpha:]]", "abcba"); #endif nerrors += VerifyScanningOneString(__FILE__, __LINE__, "ba", "%*[ab]c%[^\n]", "abcba"); return nerrors; } /************************************************************************* * */ int VerifyScanningRegression(TRIO_NOARGS) { int nerrors = 0; int rc; int index; double dnumber; trio_long_double_t ldnumber; long lnumber; int number; char ch; rc = trio_sscanf("1.5", "%lf%n", &dnumber, &index); nerrors += Verify(__FILE__, __LINE__, "1 3 1.500000", "%d %d %f", rc, index, dnumber); rc = trio_sscanf("q 123", "%c%ld", &ch, &lnumber); nerrors += Verify(__FILE__, __LINE__, "q 123", "%c %ld", ch, lnumber); rc = trio_sscanf("abc", "%*s%n", &number); nerrors += Verify(__FILE__, __LINE__, "0 3", "%d %d", rc, number); rc = trio_sscanf("abc def", "%*s%n", &number); nerrors += Verify(__FILE__, __LINE__, "0 3", "%d %d", rc, number); rc = trio_sscanf("0.141882295971771490", "%lf", &dnumber); number = 33; rc = trio_sscanf("total 1", "total %d", &number); nerrors += Verify(__FILE__, __LINE__, "1 1", "%d %d", rc, number); #if defined(TRIO_BREESE) nerrors += Verify(__FILE__, __LINE__, "1 0.141882295971771488", "%d %.18f", rc, dnumber); rc = trio_sscanf("0.141882295971771490", "%Lf", &ldnumber); nerrors += Verify(__FILE__, __LINE__, "1 0.141882295971771490", "%d %.18Lf", rc, ldnumber); #endif return nerrors; } /************************************************************************* * */ int VerifyScanning(TRIO_NOARGS) { int nerrors = 0; nerrors += VerifyScanningIntegers(); nerrors += VerifyScanningFloats(); nerrors += VerifyScanningStrings(); nerrors += VerifyScanningRegression(); return nerrors; } /************************************************************************* * */ int VerifyStrings(TRIO_NOARGS) { int nerrors = 0; #if !defined(TRIO_MINIMAL) char buffer[512]; double dnumber; float fnumber; char *end; /* Comparison */ trio_copy(buffer, "Find me now"); if (trio_length(buffer) != sizeof("Find me now") - 1) { nerrors++; Report0(__FILE__, __LINE__); } if (!trio_equal(buffer, "Find me now")) { nerrors++; Report0(__FILE__, __LINE__); } if (!trio_equal_case(buffer, "Find me now")) { nerrors++; Report0(__FILE__, __LINE__); } if (trio_equal_case(buffer, "FIND ME NOW")) { nerrors++; Report0(__FILE__, __LINE__); } if (!trio_equal_max(buffer, sizeof("Find me") - 1, "Find ME")) { nerrors++; Report0(__FILE__, __LINE__); } if (!trio_contains(buffer, "me")) { nerrors++; Report0(__FILE__, __LINE__); } if (trio_contains(buffer, "and me")) { nerrors++; Report0(__FILE__, __LINE__); } if (trio_substring(buffer, "me") == NULL) { nerrors++; Report0(__FILE__, __LINE__); } if (trio_substring_max(buffer, 4, "me") != NULL) { nerrors++; Report0(__FILE__, __LINE__); } if (!trio_match(buffer, "* me *")) { nerrors++; Report0(__FILE__, __LINE__); } if (trio_match_case(buffer, "* ME *")) { nerrors++; Report0(__FILE__, __LINE__); } if (trio_index(buffer, 'n') == NULL) { nerrors++; Report0(__FILE__, __LINE__); } if (trio_index(buffer, '_') != NULL) { nerrors++; Report0(__FILE__, __LINE__); } if (trio_index_last(buffer, 'n') == NULL) { nerrors++; Report0(__FILE__, __LINE__); } /* Append */ trio_copy(buffer, "Find me now"); if (!trio_append(buffer, " and again")) { nerrors++; Report0(__FILE__, __LINE__); } if (!trio_equal(buffer, "Find me now and again")) { nerrors++; Report0(__FILE__, __LINE__); } if (!trio_append_max(buffer, 0, "should not appear")) { nerrors++; Report0(__FILE__, __LINE__); } if (!trio_equal(buffer, "Find me now and again")) { nerrors++; Report0(__FILE__, __LINE__); } /* To upper/lower */ trio_copy(buffer, "Find me now"); trio_upper(buffer); if (!trio_equal_case(buffer, "FIND ME NOW")) { nerrors++; Report0(__FILE__, __LINE__); } trio_lower(buffer); if (!trio_equal_case(buffer, "find me now")) { nerrors++; Report0(__FILE__, __LINE__); } /* Double conversion */ trio_copy(buffer, "3.1415"); dnumber = trio_to_double(buffer, NULL); if (!DOUBLE_EQUAL(dnumber, 3.1415)) { nerrors++; Report0(__FILE__, __LINE__); } fnumber = trio_to_float(buffer, NULL); if (!FLOAT_EQUAL(fnumber, 3.1415)) { nerrors++; Report0(__FILE__, __LINE__); } /* Long conversion */ trio_copy(buffer, "3.1415"); if (trio_to_long(buffer, NULL, 10) != 3L) { nerrors++; Report0(__FILE__, __LINE__); } if (trio_to_long(buffer, NULL, 4) != 3L) { nerrors++; Report0(__FILE__, __LINE__); } trio_to_long(buffer, &end, 2); if (end != buffer) { nerrors++; Report0(__FILE__, __LINE__); } #endif /* !defined(TRIO_MINIMAL) */ return nerrors; } /************************************************************************* * */ int VerifyDynamicStrings(TRIO_NOARGS) { int nerrors = 0; #if !defined(TRIO_MINIMAL) trio_string_t *string; string = trio_xstring_duplicate("Find me now"); if (string == NULL) { nerrors++; goto error; } if (!trio_xstring_equal(string, "FIND ME NOW")) nerrors++; if (!trio_xstring_append(string, " and again") || !trio_xstring_equal(string, "FIND ME NOW AND AGAIN")) nerrors++; if (!trio_xstring_contains(string, "me")) nerrors++; if (trio_xstring_contains(string, "ME")) nerrors++; if (!trio_xstring_match(string, "* me *")) nerrors++; if (trio_xstring_match_case(string, "* ME *")) nerrors++; error: if (string) trio_string_destroy(string); #endif /* !defined(TRIO_MINIMAL) */ return nerrors; } /************************************************************************* * */ int VerifyNaN(TRIO_NOARGS) { double ninf_number = trio_ninf(); double pinf_number = trio_pinf(); double nan_number = trio_nan(); int nerrors = 0; nerrors += Verify(__FILE__, __LINE__, "-1", "%d", trio_isinf(ninf_number)); nerrors += Verify(__FILE__, __LINE__, "0", "%d", trio_isinf(42.0)); nerrors += Verify(__FILE__, __LINE__, "1", "%d", trio_isinf(pinf_number)); nerrors += Verify(__FILE__, __LINE__, "1", "%d", trio_isnan(nan_number)); nerrors += Verify(__FILE__, __LINE__, "0", "%d", trio_isnan(42.0)); return nerrors; } /************************************************************************* * */ int main(TRIO_NOARGS) { int nerrors = 0; printf("%s\n", rcsid); /* Override system locale settings */ trio_locale_set_decimal_point("."); trio_locale_set_thousand_separator(","); trio_locale_set_grouping("\3"); printf("Verifying strings\n"); nerrors += VerifyStrings(); printf("Verifying dynamic strings\n"); nerrors += VerifyDynamicStrings(); printf("Verifying special quantities\n"); nerrors += VerifyNaN(); printf("Verifying formatting\n"); nerrors += VerifyFormatting(); printf("Verifying scanning\n"); nerrors += VerifyScanning(); printf("Verifying return values\n"); nerrors += VerifyErrors(); nerrors += VerifyReturnValues(); printf("Verifying allocation\n"); nerrors += VerifyAllocate(); if (nerrors == 0) printf("Regression test suceeded\n"); else printf("Regression test failed in %d instance(s)\n", nerrors); return nerrors ? 1 : 0; }