# ansiprintf.at # # Autotest module to verify correct operation of MinGW.OSDN's suite of # ANSI compliant replacements for the printf() family of functions. # # $Id$ # # Written by Keith Marshall # Copyright (C) 2016, 2022, MinGW.OSDN Project # # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice (including the next # paragraph) shall be included in all copies or substantial portions of the # Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # # # All tests specified herein are written in the C language. # MINGW_AT_LANG([C]) # MINGW_AT_CHECK_PRINTF( FORMAT, ARGS, EXPOUT ) # --------------------------------------------- # Set up the test case to evaluate the behaviour of printf() when # invoked with the specified (unquoted) FORMAT, and the given comma # separated list of ARGS; confirm that the resultant output matches # EXPOUT, (which is interpreted as CRLF delimited text). # m4_define([MINGW_AT_CHECK_PRINTF],[dnl AT_SETUP([printf ("$1", $2)])_MINGW_AT_CHECK_PRINTF([$1],[$2],[$3])dnl ])m4_define([_MINGW_AT_CHECK_PRINTF],[dnl AT_KEYWORDS([C printf]) MINGW_AT_DATA_CRLF([expout],[[$3 ]])MINGW_AT_CHECK_RUN([[[ #define _XOPEN_SOURCE 700 #include #include int main() { printf ("::]$1[::\n", ]$2[); return 0; }]]],,[expout])dnl AT_CLEANUP ])# MINGW_AT_CHECK_PRINTF # MINGW_AT_XFAIL_PRINTF( FORMAT, ARGS, EXPOUT ) # --------------------------------------------- # A variation on MINGW_AT_CHECK_PRINTF, used to introduce any test # from which the output is likely to differ from that which might be # expected for the given format and arguments, (e.g. the display of # numeric digits beyond the limit of precision for the data type). # m4_define([MINGW_AT_XFAIL_PRINTF],[dnl AT_SETUP([printf ("$1", $2)])AT_XFAIL_IF([true])dnl _MINGW_AT_CHECK_PRINTF([$1],[$2],[$3])dnl ])# MINGW_AT_XFAIL_PRINTF # Test behaviour of "%d" format conversion, for decimal # display of integer values. # AT_BANNER([[ISO-C99 printf() integer value formatting.]]) MINGW_AT_CHECK_PRINTF([[%20d]], [+0], [:: 0::]) MINGW_AT_CHECK_PRINTF([[%+20d]], [-0], [:: +0::]) MINGW_AT_CHECK_PRINTF([[%020d]], [+0], [::00000000000000000000::]) MINGW_AT_CHECK_PRINTF([[%-20d]], [-0], [::0 ::]) MINGW_AT_CHECK_PRINTF([[%20d]], [+55], [:: 55::]) MINGW_AT_CHECK_PRINTF([[%20d]], [-55], [:: -55::]) MINGW_AT_CHECK_PRINTF([[%+20d]], [+55], [:: +55::]) MINGW_AT_CHECK_PRINTF([[%+20d]], [-55], [:: -55::]) MINGW_AT_CHECK_PRINTF([[%020d]], [+55], [::00000000000000000055::]) MINGW_AT_CHECK_PRINTF([[%-20d]], [+55], [::55 ::]) # Test behaviour of "%#x" format conversion, for hexadecimal # display of integer values. # AT_BANNER([[ISO-C99 printf() hexadecimal integer formatting.]]) MINGW_AT_CHECK_PRINTF([[%#20x]], [-0], [:: 0::]) MINGW_AT_CHECK_PRINTF([[%#+20x]], [+0], [:: 0::]) MINGW_AT_CHECK_PRINTF([[%#020x]], [-0], [::00000000000000000000::]) MINGW_AT_CHECK_PRINTF([[%#-20x]], [+0], [::0 ::]) MINGW_AT_CHECK_PRINTF([[%#20x]], [+77], [:: 0x4d::]) MINGW_AT_CHECK_PRINTF([[%#20x]], [-77], [:: 0xffffffb3::]) MINGW_AT_CHECK_PRINTF([[%#+20x]], [+77], [:: 0x4d::]) MINGW_AT_CHECK_PRINTF([[%#+20x]], [-77], [:: 0xffffffb3::]) MINGW_AT_CHECK_PRINTF([[%#020x]], [+77], [::0x00000000000000004d::]) MINGW_AT_CHECK_PRINTF([[%#-20x]], [+77], [::0x4d ::]) # Test effect of alignment and sign flags on "%f" format conversion. # AT_BANNER([[ISO-C99 printf() fixed point real number formatting.]]) MINGW_AT_CHECK_PRINTF([[%20f]], [M_E], [:: 2.718282::]) MINGW_AT_CHECK_PRINTF([[% 20f]], [M_E], [:: 2.718282::]) MINGW_AT_CHECK_PRINTF([[%+20f]], [M_E], [:: +2.718282::]) MINGW_AT_CHECK_PRINTF([[% 020f]], [M_E], [:: 000000000002.718282::]) MINGW_AT_CHECK_PRINTF([[%020f]], [M_E], [::0000000000002.718282::]) MINGW_AT_CHECK_PRINTF([[%+020f]], [M_E], [::+000000000002.718282::]) MINGW_AT_CHECK_PRINTF([[%+ 020f]], [M_E], [::+000000000002.718282::]) MINGW_AT_CHECK_PRINTF([[%-20f]], [M_E], [::2.718282 ::]) MINGW_AT_CHECK_PRINTF([[%- 20f]], [M_E], [:: 2.718282 ::]) MINGW_AT_CHECK_PRINTF([[%-+20f]], [M_E], [::+2.718282 ::]) MINGW_AT_CHECK_PRINTF([[%- +20f]], [M_E], [::+2.718282 ::]) MINGW_AT_CHECK_PRINTF([[%-020f]], [M_E], [::2.718282 ::]) # Test the effect of "%f" format conversion, with a value which # requires in excess the representable 15-digit maximum precision # of the double data type; ideally, a value with an exact binary # representation would be displayed exactly, but we expect this # to fail, with garbage beyond the 15-digit boundary. # AT_BANNER([[ISO-C99 printf() fixed point formatting imprecision.]]) MINGW_AT_XFAIL_PRINTF([[%30.1f]], [1e+26], [:: 100000000000000000000000000.0::]) # Test default behaviour of "%g" format conversion; (this should # have no non-significant trailing zeros, nor should it end with # a radix point without following non-zero fractional digits). # AT_BANNER([[ISO-C99 printf() floating point real number formatting.]]) MINGW_AT_CHECK_PRINTF([[%20g]], [1.75e+02], [:: 175::]) MINGW_AT_CHECK_PRINTF([[%20g]], [1.75e+05], [:: 175000::]) MINGW_AT_CHECK_PRINTF([[%20g]], [1.75e+15], [:: 1.75e+015::]) MINGW_AT_CHECK_PRINTF([[%20g]], [1.75e+00], [:: 1.75::]) MINGW_AT_CHECK_PRINTF([[%20g]], [1.75e-03], [:: 0.00175::]) MINGW_AT_CHECK_PRINTF([[%20g]], [1.75e-15], [:: 1.75e-015::]) # Test effect of alignment and sign flags on "%g" format conversion. # AT_BANNER([[ISO-C99 printf() floating point formatting with flags.]]) MINGW_AT_CHECK_PRINTF([[%+20g]], [M_E], [:: +2.71828::]) MINGW_AT_CHECK_PRINTF([[%020g]], [M_E], [::00000000000002.71828::]) MINGW_AT_CHECK_PRINTF([[% 020g]], [M_E], [:: 0000000000002.71828::]) MINGW_AT_CHECK_PRINTF([[%+020g]], [M_E], [::+0000000000002.71828::]) MINGW_AT_CHECK_PRINTF([[%+ 020g]], [M_E], [::+0000000000002.71828::]) MINGW_AT_CHECK_PRINTF([[%-20g]], [M_E], [::2.71828 ::]) MINGW_AT_CHECK_PRINTF([[%- 20g]], [M_E], [:: 2.71828 ::]) MINGW_AT_CHECK_PRINTF([[%-+20g]], [M_E], [::+2.71828 ::]) MINGW_AT_CHECK_PRINTF([[%- +20g]], [M_E], [::+2.71828 ::]) MINGW_AT_CHECK_PRINTF([[%-020g]], [M_E], [::2.71828 ::]) # Test effect of "#" flag on "%g" format conversion; (this should # override suppression of non-significant trailing zeros). # AT_BANNER([[ISO-C99 printf() alternative floating point formatting.]]) MINGW_AT_CHECK_PRINTF([[%#20g]], [1.75e+02], [:: 175.000::]) MINGW_AT_CHECK_PRINTF([[%#20g]], [1.75e+05], [:: 175000.::]) MINGW_AT_CHECK_PRINTF([[%#20g]], [1.75e+15], [:: 1.75000e+015::]) MINGW_AT_CHECK_PRINTF([[%#20g]], [1.75e+00], [:: 1.75000::]) MINGW_AT_CHECK_PRINTF([[%#20g]], [1.75e-03], [:: 0.00175000::]) MINGW_AT_CHECK_PRINTF([[%#20g]], [1.75e-15], [:: 1.75000e-015::]) # Test transition between "%e" and "%f" style representations, for # default precision "%g" format conversion. # AT_BANNER([[ISO-C99 printf() floating point format style transitions.]]) MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e-6], [:: 2.71828e-006::]) MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e-5], [:: 2.71828e-005::]) MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e-4], [:: 0.000271828::]) MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e-3], [:: 0.00271828::]) MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e-2], [:: 0.0271828::]) MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e-1], [:: 0.271828::]) MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e+0], [:: 2.71828::]) MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e+1], [:: 27.1828::]) MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e+2], [:: 271.828::]) MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e+3], [:: 2718.28::]) MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e+4], [:: 27182.8::]) MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e+5], [:: 271828::]) MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e+6], [:: 2.71828e+006::]) MINGW_AT_CHECK_PRINTF([[%20g]], [M_E * 1e+7], [:: 2.71828e+007::]) # Test the effect of varying precision, as specified by the "*" format # modifier, on "%g" format conversion; (-ve precision implies default; # zero or +ve specifies actual significant digits). # AT_BANNER([[ISO-C99 printf() variable precision floating point format.]]) MINGW_AT_CHECK_PRINTF([[%20.*g]], [-2, M_E], [:: 2.71828::]) MINGW_AT_CHECK_PRINTF([[%20.*g]], [-1, M_E], [:: 2.71828::]) MINGW_AT_CHECK_PRINTF([[%20.*g]], [+0, M_E], [:: 3::]) MINGW_AT_CHECK_PRINTF([[%20.*g]], [+1, M_E], [:: 3::]) MINGW_AT_CHECK_PRINTF([[%20.*g]], [+2, M_E], [:: 2.7::]) MINGW_AT_CHECK_PRINTF([[%20.*g]], [+3, M_E], [:: 2.72::]) MINGW_AT_CHECK_PRINTF([[%20.*g]], [+4, M_E], [:: 2.718::]) MINGW_AT_CHECK_PRINTF([[%20.*g]], [+5, M_E], [:: 2.7183::]) MINGW_AT_CHECK_PRINTF([[%20.*g]], [+6, M_E], [:: 2.71828::]) MINGW_AT_CHECK_PRINTF([[%20.*g]], [+7, M_E], [:: 2.718282::]) MINGW_AT_CHECK_PRINTF([[%20.*g]], [+8, M_E], [:: 2.7182818::]) # Test variations of "%e" format conversion. # AT_BANNER([[ISO-C99 printf() scientific style floating point format.]]) MINGW_AT_CHECK_PRINTF([[%20.7e]], [+M_E * 0.0], [:: 0.0000000e+000::]) MINGW_AT_CHECK_PRINTF([[%20.7e]], [-M_E * 0.0], [:: -0.0000000e+000::]) MINGW_AT_CHECK_PRINTF([[%20.7e]], [+M_E * 1.0], [:: 2.7182818e+000::]) MINGW_AT_CHECK_PRINTF([[%20.7e]], [-M_E * 1.0], [:: -2.7182818e+000::]) MINGW_AT_CHECK_PRINTF([[%20.7e]], [+M_E / 0.0], [:: inf::]) MINGW_AT_CHECK_PRINTF([[%20.7e]], [-M_E / 0.0], [:: -inf::]) MINGW_AT_CHECK_PRINTF([[%20.7e]], [-0.0 / 0.0], [:: nan::]) MINGW_AT_CHECK_PRINTF([[%-20.7e]], [+M_E * 0.0], [::0.0000000e+000 ::]) MINGW_AT_CHECK_PRINTF([[%-20.7e]], [-M_E * 0.0], [::-0.0000000e+000 ::]) MINGW_AT_CHECK_PRINTF([[%-20.7e]], [+M_E * 1.0], [::2.7182818e+000 ::]) MINGW_AT_CHECK_PRINTF([[%-20.7e]], [-M_E * 1.0], [::-2.7182818e+000 ::]) MINGW_AT_CHECK_PRINTF([[%-20.7e]], [+M_E / 0.0], [::inf ::]) MINGW_AT_CHECK_PRINTF([[%-20.7e]], [-M_E / 0.0], [::-inf ::]) MINGW_AT_CHECK_PRINTF([[%-20.7e]], [-0.0 / 0.0], [::nan ::]) MINGW_AT_CHECK_PRINTF([[%+20.7e]], [+M_E * 0.0], [:: +0.0000000e+000::]) MINGW_AT_CHECK_PRINTF([[%+20.7e]], [-M_E * 0.0], [:: -0.0000000e+000::]) MINGW_AT_CHECK_PRINTF([[%+20.7e]], [+M_E * 1.0], [:: +2.7182818e+000::]) MINGW_AT_CHECK_PRINTF([[%+20.7e]], [-M_E * 1.0], [:: -2.7182818e+000::]) MINGW_AT_CHECK_PRINTF([[%+20.7e]], [+M_E / 0.0], [:: +inf::]) MINGW_AT_CHECK_PRINTF([[%+20.7e]], [-M_E / 0.0], [:: -inf::]) MINGW_AT_CHECK_PRINTF([[%+20.7e]], [-0.0 / 0.0], [:: +nan::]) # Test variations of "%a" format conversion; (the following integer # value confirms correct size of the floating point entity passed on # the printf() argument stack). # AT_BANNER([[ISO-C99 printf() hexadecimal floating point formatting.]]) MINGW_AT_CHECK_PRINTF([[%16a%4d]], [0.000, 77], [:: 0x0p+0 77::]) MINGW_AT_CHECK_PRINTF([[%16.3a%4d]], [0.000, 99], [:: 0x0.000p+0 99::]) MINGW_AT_CHECK_PRINTF([[%16a%4d]], [1.750, 77], [:: 0xep-3 77::]) MINGW_AT_CHECK_PRINTF([[%016a%4d]], [1.750, 77], [::0x0000000000ep-3 77::]) MINGW_AT_CHECK_PRINTF([[%-016a%4d]], [1.750, 77], [::0xep-3 77::]) MINGW_AT_CHECK_PRINTF([[%16.0a%4d]], [1.450, 44], [:: 0xcp-3 44::]) MINGW_AT_CHECK_PRINTF([[%16.1a%4d]], [1.999, 99], [:: 0x8.0p-2 99::]) MINGW_AT_CHECK_PRINTF([[%16La%4d]], [1.750L, 77], [:: 0xep-3 77::]) MINGW_AT_CHECK_PRINTF([[%016La%4d]], [1.750L, 77], [::0x0000000000ep-3 77::]) MINGW_AT_CHECK_PRINTF([[%16.0La%4d]], [1.450L, 44], [:: 0xcp-3 44::]) MINGW_AT_CHECK_PRINTF([[%16.1La%4d]], [1.999L, 99], [:: 0x8.0p-2 99::]) # MINGW_AT_CHECK_SNPRINTF( FORMAT, COUNT, MAXCOUNT, INITCOUNT ) # ------------------------------------------------------------- # Test the behaviour of the snprintf() function, with respect to # output truncation at specified MAXCOUNT (no more than 32), when # writing string "Sample text; sufficient buffer" subject to the # specified FORMAT and COUNT (concatenated to define the format # string). Also supports testing the effect of "%n" counting on # an internal integer variable, initialized to INITCOUNT, when # COUNT is specified as "n", (with optional "hh" length modifier # prefix; if this option is not to be exercised, FORMAT should # be passed as "%", with COUNT as "s"). # m4_define([MINGW_AT_CHECK_SNPRINTF],[dnl AT_SETUP([snprintf (output, $3, "$1$2", ...)]) AT_KEYWORDS([C printf])MINGW_AT_DATA_CRLF([expout],[[$5 ]])MINGW_AT_CHECK_RUN([[[ #define _XOPEN_SOURCE 700 #include int main() { char output[32]; union { int n; char hhn; } capture = {]$4[}; const char *sample = "Sample text; sufficient buffer"; int total = snprintf (output, ]$3[, "]$1$2[", sample]m4_if([$2],[s],]dnl [,[, &capture.$2])[); snprintf (NULL, 0, "]$1$2[", output]m4_if([$2],[s],,[, &capture.$2])[); printf ("%s: %d required; %d captured\n", output, total, capture.n); return 0; }]]],,[expout])dnl AT_CLEANUP ])# MINGW_AT_CHECK_SNPRINTF # Tests for snprintf() with limited length internal buffer. # AT_BANNER([ISO-C99 snprintf() buffer length control.]) MINGW_AT_CHECK_SNPRINTF([[%]],[s],[32],[1024],dnl [Sample text; sufficient buffer: 30 required; 1024 captured]) MINGW_AT_CHECK_SNPRINTF([[%]],[s],[12],[1024],dnl [Sample text: 30 required; 1024 captured]) # Tests for effect of "%n" output length counting. # AT_BANNER([ISO-C99 snprintf() intermediate output counting.]) MINGW_AT_CHECK_SNPRINTF([[%s%]],[n],[32],[1024],dnl [Sample text; sufficient buffer: 30 required; 30 captured]) MINGW_AT_CHECK_SNPRINTF([[%s%]],[n],[12],[1024],dnl [Sample text: 30 required; 11 captured]) MINGW_AT_CHECK_SNPRINTF([[%s%]],[hhn],[12],[1024],dnl [Sample text: 30 required; 1035 captured]) # vim: filetype=config formatoptions=croql # $RCSfile$: end of file