xref: /openbsd/regress/lib/libc/wprintf/wfp.c (revision e5dd7070)
1 /*	$OpenBSD: wfp.c,v 1.2 2020/01/13 16:51:04 bluhm Exp $	*/
2 /*-
3  * Copyright (c) 2002, 2005 David Schultz <das@FreeBSD.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 /*
29  * Test for wprintf() floating point formats.
30  */
31 
32 #include <assert.h>
33 #include <err.h>
34 #include <float.h>
35 #include <math.h>
36 #include <stdio.h>
37 #include <stdarg.h>
38 #include <stdint.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <wchar.h>
42 
43 #define	testfmt(result, fmt, ...)	\
44 	_testfmt((result), __LINE__, #__VA_ARGS__, fmt, __VA_ARGS__)
45 void _testfmt(const wchar_t *, int, const char *, const wchar_t *, ...);
46 void smash_stack(void);
47 
48 int
49 main(int argc, char *argv[])
50 {
51 	/*
52 	 * Basic tests of decimal output functionality.
53 	 */
54 	testfmt(L" 1.000000E+00", L"%13E", 1.0);
55 	testfmt(L"     1.000000", L"%13f", 1.0);
56 	testfmt(L"            1", L"%13G", 1.0);
57 	testfmt(L" 1.000000E+00", L"%13LE", 1.0L);
58 	testfmt(L"     1.000000", L"%13Lf", 1.0L);
59 	testfmt(L"            1", L"%13LG", 1.0L);
60 
61 	testfmt(L"2.718282", L"%.*f", -2, 2.7182818);
62 
63 	testfmt(L"1.234568e+06", L"%e", 1234567.8);
64 	testfmt(L"1234567.800000", L"%f", 1234567.8);
65 	testfmt(L"1.23457E+06", L"%G", 1234567.8);
66 	testfmt(L"1.234568e+06", L"%Le", 1234567.8L);
67 	testfmt(L"1234567.800000", L"%Lf", 1234567.8L);
68 	testfmt(L"1.23457E+06", L"%LG", 1234567.8L);
69 
70 #if (LDBL_MANT_DIG > DBL_MANT_DIG) && !defined(__i386__)
71 	testfmt(L"123456789.864210", L"%Lf", 123456789.8642097531L);
72 	testfmt(L"-1.23457E+08", L"%LG", -123456789.8642097531L);
73 	testfmt(L"123456789.8642097531", L"%.10Lf", 123456789.8642097531L);
74 	testfmt(L" 3.141592653589793238e-4000", L"%L27.18Le",
75 	    3.14159265358979323846e-4000L);
76 #endif /* (LDBL_MANT_DIG > DBL_MANT_DIG) && !defined(__i386__) */
77 
78 	/*
79 	 * Infinities and NaNs
80 	 */
81 #ifdef NAN
82 	testfmt(L"nan", L"%e", NAN);
83 	testfmt(L"NAN", L"%F", NAN);
84 	testfmt(L"nan", L"%g", NAN);
85 	testfmt(L"NAN", L"%LE", (long double)NAN);
86 	testfmt(L"  nan", L"%05e", NAN);
87 #endif /* NAN */
88 
89 	testfmt(L"INF", L"%E", HUGE_VAL);
90 	testfmt(L"-inf", L"%f", -HUGE_VAL);
91 	testfmt(L"+inf", L"%+g", HUGE_VAL);
92 	testfmt(L" inf", L"%4.2Le", HUGE_VALL);
93 	testfmt(L"-inf", L"%Lf", -HUGE_VALL);
94 	testfmt(L"  inf", L"%05e", HUGE_VAL);
95 	testfmt(L" -inf", L"%05e", -HUGE_VAL);
96 
97 	/*
98 	 * Padding
99 	 */
100 	testfmt(L"0.000000e+00", L"%e", 0.0);
101 	testfmt(L"0.000000", L"%F", (double)0.0);
102 	testfmt(L"0", L"%G", 0.0);
103 	testfmt(L"  0", L"%3.0Lg", 0.0L);
104 	testfmt(L"    0", L"%5.0f", 0.001);
105 
106 	/*
107 	 * Precision specifiers
108 	 */
109 	testfmt(L"1.0123e+00", L"%.4e", 1.0123456789);
110 	testfmt(L"1.0123", L"%.4f", 1.0123456789);
111 	testfmt(L"1.012", L"%.4g", 1.0123456789);
112 	testfmt(L"1.2346e-02", L"%.4e", 0.0123456789);
113 	testfmt(L"0.0123", L"%.4f", 0.0123456789);
114 	testfmt(L"0.01235", L"%.4g", 0.0123456789);
115 
116 	/*
117 	 * Signed conversions
118 	 */
119 	testfmt(L"+2.500000e-01", L"%+e", 0.25);
120 	testfmt(L"+0.000000", L"%+F", 0.0);
121 	testfmt(L"-1", L"%+g", -1.0);
122 
123 	testfmt(L"-1.000000e+00", L"% e", -1.0);
124 	testfmt(L"+1.000000", L"% +f", 1.0);
125 	testfmt(L" 1", L"% g", 1.0);
126 	testfmt(L" 0", L"% g", 0.0);
127 
128 	/*
129 	 * ``Alternate form''
130 	 */
131 	testfmt(L"1.250e+00", L"%#.3e", 1.25);
132 	testfmt(L"123.000000", L"%#f", 123.0);
133 	testfmt(L" 12345.", L"%#7.5g", 12345.0);
134 	testfmt(L" 1.00000", L"%#8g", 1.0);
135 	testfmt(L"0.0", L"%#.2g", 0.0);
136 
137 	/*
138 	 * Padding and decimal point placement
139 	 */
140 	testfmt(L"03.2E+00", L"%08.1E", 3.25);
141 	testfmt(L"003.25", L"%06.2F", 3.25);
142 	testfmt(L"0003.25", L"%07.4G", 3.25);
143 
144 	testfmt(L"3.14159e-05", L"%g", 3.14159e-5);
145 	testfmt(L"0.000314159", L"%g", 3.14159e-4);
146 	testfmt(L"3.14159e+06", L"%g", 3.14159e6);
147 	testfmt(L"314159", L"%g", 3.14159e5);
148 	testfmt(L"314159.", L"%#g", 3.14159e5);
149 
150 	testfmt(L" 9.000000e+03", L"%13e", 9000.0);
151 	testfmt(L" 9000.000000", L"%12f", 9000.0);
152 	testfmt(L" 9000", L"%5g", 9000.0);
153 	testfmt(L" 900000.", L"%#8g", 900000.0);
154 	testfmt(L" 9e+06", L"%6g", 9000000.0);
155 	testfmt(L" 9.000000e-04", L"%13e", 0.0009);
156 	testfmt(L" 0.000900", L"%9f", 0.0009);
157 	testfmt(L" 0.0009", L"%7g", 0.0009);
158 	testfmt(L" 9e-05", L"%6g", 0.00009);
159 	testfmt(L" 9.00000e-05", L"%#12g", 0.00009);
160 	testfmt(L" 9.e-05", L"%#7.1g", 0.00009);
161 
162 	testfmt(L" 0.0", L"%4.1f", 0.0);
163 	testfmt(L"90.0", L"%4.1f", 90.0);
164 	testfmt(L" 100", L"%4.0f", 100.0);
165 	testfmt(L"9.0e+01", L"%4.1e", 90.0);
166 	testfmt(L"1e+02", L"%4.0e", 100.0);
167 
168 	/*
169 	 * Hexadecimal floating point (%a, %A) tests.  Some of these
170 	 * are only valid if the implementation converts to hex digits
171 	 * on nibble boundaries.
172 	 */
173 	testfmt(L"0x0p+0", L"%a", 0x0.0p0);
174 	testfmt(L"0X0.P+0", L"%#LA", 0x0.0p0L);
175 #ifdef NAN
176 	testfmt(L"inf", L"%La", (long double)INFINITY);
177 	testfmt(L"+INF", L"%+A", INFINITY);
178 	testfmt(L"nan", L"%La", (long double)NAN);
179 	testfmt(L"NAN", L"%A", NAN);
180 #endif /* NAN */
181 
182 	testfmt(L" 0x1.23p+0", L"%10a", 0x1.23p0);
183 	testfmt(L" 0x1.23p-500", L"%12a", 0x1.23p-500);
184 	testfmt(L" 0x1.2p+40", L"%10.1a", 0x1.23p40);
185 	testfmt(L" 0X1.230000000000000000000000P-4", L"%32.24A", 0x1.23p-4);
186 	testfmt(L"0x1p-1074", L"%a", 0x1p-1074);
187 	testfmt(L"0x1.2345p-1024", L"%a", 0x1.2345p-1024);
188 
189 	return (0);
190 }
191 
192 void
193 smash_stack(void)
194 {
195 	static uint32_t junk = 0xdeadbeef;
196 	uint32_t buf[512];
197 	int i;
198 
199 	for (i = 0; i < sizeof(buf) / sizeof(buf[0]); i++)
200 		buf[i] = junk;
201 }
202 
203 void
204 _testfmt(const wchar_t *result, int line, const char *argstr,
205     const wchar_t *fmt, ...)
206 {
207 	wchar_t ws[100];
208 	va_list ap;
209 
210 	va_start(ap, fmt);
211 	smash_stack();
212 	vswprintf(ws, sizeof(ws)/sizeof(ws[0]), fmt, ap);
213 	if (wcscmp(result, ws) != 0) {
214 		const wchar_t *p = ws;
215 		char f[100], s[100], r[100];
216 
217 		memset(f, 0, sizeof(f));
218 		memset(s, 0, sizeof(s));
219 		memset(r, 0, sizeof(r));
220 		wcsrtombs(f, &fmt, sizeof(f) - 1, NULL);
221 		wcsrtombs(s, &p, sizeof(s) - 1, NULL);
222 		wcsrtombs(r, &result, sizeof(r) - 1, NULL);
223 
224 		errx(1, "line %d: printf(\"%s\", %s) ==> [%s], expected [%s]",
225 		    line, f, argstr, s, r);
226 	}
227 }
228