]>
Commit | Line | Data |
---|---|---|
688903eb | 1 | /* Copyright (C) 1991-2018 Free Software Foundation, Inc. |
c84142e8 UD |
2 | This file is part of the GNU C Library. |
3 | ||
4 | The GNU C Library is free software; you can redistribute it and/or | |
41bdb6e2 AJ |
5 | modify it under the terms of the GNU Lesser General Public |
6 | License as published by the Free Software Foundation; either | |
7 | version 2.1 of the License, or (at your option) any later version. | |
c84142e8 UD |
8 | |
9 | The GNU C Library is distributed in the hope that it will be useful, | |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
41bdb6e2 | 12 | Lesser General Public License for more details. |
c84142e8 | 13 | |
41bdb6e2 | 14 | You should have received a copy of the GNU Lesser General Public |
59ba27a6 PE |
15 | License along with the GNU C Library; if not, see |
16 | <http://www.gnu.org/licenses/>. */ | |
28f540f4 | 17 | |
28f540f4 RM |
18 | #ifdef BSD |
19 | #include </usr/include/stdio.h> | |
20 | #define EXIT_SUCCESS 0 | |
21 | #else | |
b3f7c665 | 22 | #include <limits.h> |
28f540f4 RM |
23 | #include <stdio.h> |
24 | #include <stdlib.h> | |
25 | #include <string.h> | |
26 | #endif | |
27 | ||
28 | #include <float.h> | |
e15f7de6 | 29 | #include <libc-diag.h> |
1c4053db RM |
30 | |
31 | /* This whole file is picayune tests of corner cases of printf format strings. | |
32 | The compiler warnings are not useful here. */ | |
33 | DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wformat"); | |
28f540f4 | 34 | |
9032070d | 35 | #if __GNUC_PREREQ (7, 0) |
3c937826 JM |
36 | /* Compiler warnings about snprintf output truncation should also be |
37 | ignored. */ | |
38 | DIAG_IGNORE_NEEDS_COMMENT (7.0, "-Wformat-truncation"); | |
9032070d SE |
39 | #endif |
40 | ||
1a511d31 AJ |
41 | static void rfg1 (void); |
42 | static void rfg2 (void); | |
75bfdfc7 | 43 | static void rfg3 (void); |
11336c16 | 44 | |
28f540f4 | 45 | |
1a511d31 | 46 | static void |
11336c16 | 47 | fmtchk (const char *fmt) |
28f540f4 RM |
48 | { |
49 | (void) fputs(fmt, stdout); | |
50 | (void) printf(":\t`"); | |
51 | (void) printf(fmt, 0x12); | |
52 | (void) printf("'\n"); | |
53 | } | |
54 | ||
1a511d31 | 55 | static void |
11336c16 | 56 | fmtst1chk (const char *fmt) |
28f540f4 RM |
57 | { |
58 | (void) fputs(fmt, stdout); | |
59 | (void) printf(":\t`"); | |
60 | (void) printf(fmt, 4, 0x12); | |
61 | (void) printf("'\n"); | |
62 | } | |
63 | ||
1a511d31 | 64 | static void |
11336c16 | 65 | fmtst2chk (const char *fmt) |
28f540f4 RM |
66 | { |
67 | (void) fputs(fmt, stdout); | |
68 | (void) printf(":\t`"); | |
69 | (void) printf(fmt, 4, 4, 0x12); | |
70 | (void) printf("'\n"); | |
71 | } | |
28f540f4 | 72 | |
c1f41083 AS |
73 | static int |
74 | do_test (void) | |
28f540f4 RM |
75 | { |
76 | static char shortstr[] = "Hi, Z."; | |
77 | static char longstr[] = "Good morning, Doctor Chandra. This is Hal. \ | |
78 | I am ready for my first lesson today."; | |
31c46cf5 | 79 | int result = 0; |
28f540f4 RM |
80 | |
81 | fmtchk("%.4x"); | |
82 | fmtchk("%04x"); | |
83 | fmtchk("%4.4x"); | |
84 | fmtchk("%04.4x"); | |
85 | fmtchk("%4.3x"); | |
86 | fmtchk("%04.3x"); | |
87 | ||
88 | fmtst1chk("%.*x"); | |
89 | fmtst1chk("%0*x"); | |
90 | fmtst2chk("%*.*x"); | |
91 | fmtst2chk("%0*.*x"); | |
92 | ||
93 | #ifndef BSD | |
ceeeaa3d | 94 | printf("bad format:\t\"%b\"\n"); |
1f64ac13 | 95 | printf("nil pointer (padded):\t\"%10p\"\n", (void *) NULL); |
28f540f4 RM |
96 | #endif |
97 | ||
98 | printf("decimal negative:\t\"%d\"\n", -2345); | |
99 | printf("octal negative:\t\"%o\"\n", -2345); | |
100 | printf("hex negative:\t\"%x\"\n", -2345); | |
101 | printf("long decimal number:\t\"%ld\"\n", -123456L); | |
102 | printf("long octal negative:\t\"%lo\"\n", -2345L); | |
103 | printf("long unsigned decimal number:\t\"%lu\"\n", -123456L); | |
104 | printf("zero-padded LDN:\t\"%010ld\"\n", -123456L); | |
75bfdfc7 | 105 | printf("left-adjusted ZLDN:\t\"%-010ld\"\n", -123456L); |
28f540f4 RM |
106 | printf("space-padded LDN:\t\"%10ld\"\n", -123456L); |
107 | printf("left-adjusted SLDN:\t\"%-10ld\"\n", -123456L); | |
108 | ||
109 | printf("zero-padded string:\t\"%010s\"\n", shortstr); | |
110 | printf("left-adjusted Z string:\t\"%-010s\"\n", shortstr); | |
111 | printf("space-padded string:\t\"%10s\"\n", shortstr); | |
112 | printf("left-adjusted S string:\t\"%-10s\"\n", shortstr); | |
6f30e59f JM |
113 | /* GCC 9 warns about the NULL format argument; this is deliberately |
114 | tested here. */ | |
115 | DIAG_PUSH_NEEDS_COMMENT; | |
116 | #if __GNUC_PREREQ (7, 0) | |
117 | DIAG_IGNORE_NEEDS_COMMENT (9, "-Wformat-overflow="); | |
118 | #endif | |
28f540f4 | 119 | printf("null string:\t\"%s\"\n", (char *)NULL); |
6f30e59f | 120 | DIAG_POP_NEEDS_COMMENT; |
28f540f4 RM |
121 | printf("limited string:\t\"%.22s\"\n", longstr); |
122 | ||
179dcdb7 TMQMF |
123 | printf("a-style max:\t\"%a\"\n", DBL_MAX); |
124 | printf("a-style -max:\t\"%a\"\n", -DBL_MAX); | |
28f540f4 RM |
125 | printf("e-style >= 1:\t\"%e\"\n", 12.34); |
126 | printf("e-style >= .1:\t\"%e\"\n", 0.1234); | |
127 | printf("e-style < .1:\t\"%e\"\n", 0.001234); | |
128 | printf("e-style big:\t\"%.60e\"\n", 1e20); | |
129 | printf ("e-style == .1:\t\"%e\"\n", 0.1); | |
130 | printf("f-style >= 1:\t\"%f\"\n", 12.34); | |
131 | printf("f-style >= .1:\t\"%f\"\n", 0.1234); | |
132 | printf("f-style < .1:\t\"%f\"\n", 0.001234); | |
133 | printf("g-style >= 1:\t\"%g\"\n", 12.34); | |
134 | printf("g-style >= .1:\t\"%g\"\n", 0.1234); | |
135 | printf("g-style < .1:\t\"%g\"\n", 0.001234); | |
136 | printf("g-style big:\t\"%.60g\"\n", 1e20); | |
137 | ||
138 | printf (" %6.5f\n", .099999999860301614); | |
139 | printf (" %6.5f\n", .1); | |
140 | printf ("x%5.4fx\n", .5); | |
141 | ||
142 | printf ("%#03x\n", 1); | |
143 | ||
1a6d7967 | 144 | printf ("something really insane: %.10000f\n", 1.0); |
a0e5d73a | 145 | |
28f540f4 RM |
146 | { |
147 | double d = FLT_MIN; | |
148 | int niter = 17; | |
299a95b9 | 149 | |
28f540f4 RM |
150 | while (niter-- != 0) |
151 | printf ("%.17e\n", d / 2); | |
152 | fflush (stdout); | |
153 | } | |
154 | ||
155 | printf ("%15.5e\n", 4.9406564584124654e-324); | |
156 | ||
157 | #define FORMAT "|%12.4f|%12.4e|%12.4g|\n" | |
158 | printf (FORMAT, 0.0, 0.0, 0.0); | |
159 | printf (FORMAT, 1.0, 1.0, 1.0); | |
160 | printf (FORMAT, -1.0, -1.0, -1.0); | |
161 | printf (FORMAT, 100.0, 100.0, 100.0); | |
162 | printf (FORMAT, 1000.0, 1000.0, 1000.0); | |
163 | printf (FORMAT, 10000.0, 10000.0, 10000.0); | |
164 | printf (FORMAT, 12345.0, 12345.0, 12345.0); | |
165 | printf (FORMAT, 100000.0, 100000.0, 100000.0); | |
166 | printf (FORMAT, 123456.0, 123456.0, 123456.0); | |
167 | #undef FORMAT | |
168 | ||
169 | { | |
170 | char buf[20]; | |
a1648746 | 171 | char buf2[512]; |
28f540f4 | 172 | printf ("snprintf (\"%%30s\", \"foo\") == %d, \"%.*s\"\n", |
75bfdfc7 UD |
173 | snprintf (buf, sizeof (buf), "%30s", "foo"), (int) sizeof (buf), |
174 | buf); | |
175 | printf ("snprintf (\"%%.999999u\", 10) == %d\n", | |
a1648746 | 176 | snprintf(buf2, sizeof(buf2), "%.999999u", 10)); |
28f540f4 RM |
177 | } |
178 | ||
5a357506 FW |
179 | printf("%.8f\n", DBL_MAX); |
180 | printf("%.8f\n", -DBL_MAX); | |
28f540f4 RM |
181 | printf ("%e should be 1.234568e+06\n", 1234567.8); |
182 | printf ("%f should be 1234567.800000\n", 1234567.8); | |
183 | printf ("%g should be 1.23457e+06\n", 1234567.8); | |
184 | printf ("%g should be 123.456\n", 123.456); | |
185 | printf ("%g should be 1e+06\n", 1000000.0); | |
186 | printf ("%g should be 10\n", 10.0); | |
187 | printf ("%g should be 0.02\n", 0.02); | |
188 | ||
c06b947e UD |
189 | #if 0 |
190 | /* This test rather checks the way the compiler handles constant | |
191 | folding. gcc behavior wrt to this changed in 3.2 so it is not a | |
192 | portable test. */ | |
28f540f4 RM |
193 | { |
194 | double x=1.0; | |
195 | printf("%.17f\n",(1.0/x/10.0+1.0)*x-x); | |
196 | } | |
c06b947e | 197 | #endif |
28f540f4 | 198 | |
299a95b9 RM |
199 | { |
200 | char buf[200]; | |
299a95b9 RM |
201 | |
202 | sprintf(buf,"%*s%*s%*s",-1,"one",-20,"two",-30,"three"); | |
203 | ||
31c46cf5 UD |
204 | result |= strcmp (buf, |
205 | "onetwo three "); | |
299a95b9 RM |
206 | |
207 | puts (result != 0 ? "Test failed!" : "Test ok."); | |
299a95b9 | 208 | } |
31c46cf5 UD |
209 | |
210 | { | |
211 | char buf[200]; | |
212 | ||
213 | sprintf (buf, "%07Lo", 040000000000ll); | |
0755050e | 214 | printf ("sprintf (buf, \"%%07Lo\", 040000000000ll) = %s", buf); |
31c46cf5 UD |
215 | |
216 | if (strcmp (buf, "40000000000") != 0) | |
217 | { | |
218 | result = 1; | |
219 | fputs ("\tFAILED", stdout); | |
220 | } | |
221 | puts (""); | |
222 | } | |
223 | ||
b3f7c665 UD |
224 | printf ("printf (\"%%hhu\", %u) = %hhu\n", UCHAR_MAX + 2, UCHAR_MAX + 2); |
225 | printf ("printf (\"%%hu\", %u) = %hu\n", USHRT_MAX + 2, USHRT_MAX + 2); | |
d2dc7b08 UD |
226 | printf ("printf (\"%%hhi\", %i) = %hhi\n", UCHAR_MAX + 2, UCHAR_MAX + 2); |
227 | printf ("printf (\"%%hi\", %i) = %hi\n", USHRT_MAX + 2, USHRT_MAX + 2); | |
228 | ||
229 | printf ("printf (\"%%1$hhu\", %2$u) = %1$hhu\n", | |
230 | UCHAR_MAX + 2, UCHAR_MAX + 2); | |
231 | printf ("printf (\"%%1$hu\", %2$u) = %1$hu\n", USHRT_MAX + 2, USHRT_MAX + 2); | |
232 | printf ("printf (\"%%1$hhi\", %2$i) = %1$hhi\n", | |
233 | UCHAR_MAX + 2, UCHAR_MAX + 2); | |
234 | printf ("printf (\"%%1$hi\", %2$i) = %1$hi\n", USHRT_MAX + 2, USHRT_MAX + 2); | |
b3f7c665 | 235 | |
0755050e UD |
236 | puts ("--- Should be no further output. ---"); |
237 | rfg1 (); | |
238 | rfg2 (); | |
75bfdfc7 | 239 | rfg3 (); |
0755050e | 240 | |
b3f7c665 UD |
241 | { |
242 | char bytes[7]; | |
243 | char buf[20]; | |
244 | ||
245 | memset (bytes, '\xff', sizeof bytes); | |
246 | sprintf (buf, "foo%hhn\n", &bytes[3]); | |
247 | if (bytes[0] != '\xff' || bytes[1] != '\xff' || bytes[2] != '\xff' | |
248 | || bytes[4] != '\xff' || bytes[5] != '\xff' || bytes[6] != '\xff') | |
249 | { | |
250 | puts ("%hhn overwrite more bytes"); | |
251 | result = 1; | |
252 | } | |
253 | if (bytes[3] != 3) | |
254 | { | |
255 | puts ("%hhn wrote incorrect value"); | |
256 | result = 1; | |
257 | } | |
258 | } | |
259 | ||
31c46cf5 | 260 | return result != 0; |
28f540f4 RM |
261 | } |
262 | \f | |
1a511d31 | 263 | static void |
11336c16 | 264 | rfg1 (void) |
28f540f4 RM |
265 | { |
266 | char buf[100]; | |
267 | ||
268 | sprintf (buf, "%5.s", "xyz"); | |
269 | if (strcmp (buf, " ") != 0) | |
270 | printf ("got: '%s', expected: '%s'\n", buf, " "); | |
271 | sprintf (buf, "%5.f", 33.3); | |
272 | if (strcmp (buf, " 33") != 0) | |
273 | printf ("got: '%s', expected: '%s'\n", buf, " 33"); | |
274 | sprintf (buf, "%8.e", 33.3e7); | |
275 | if (strcmp (buf, " 3e+08") != 0) | |
276 | printf ("got: '%s', expected: '%s'\n", buf, " 3e+08"); | |
277 | sprintf (buf, "%8.E", 33.3e7); | |
278 | if (strcmp (buf, " 3E+08") != 0) | |
279 | printf ("got: '%s', expected: '%s'\n", buf, " 3E+08"); | |
280 | sprintf (buf, "%.g", 33.3); | |
281 | if (strcmp (buf, "3e+01") != 0) | |
282 | printf ("got: '%s', expected: '%s'\n", buf, "3e+01"); | |
283 | sprintf (buf, "%.G", 33.3); | |
284 | if (strcmp (buf, "3E+01") != 0) | |
285 | printf ("got: '%s', expected: '%s'\n", buf, "3E+01"); | |
28f540f4 RM |
286 | } |
287 | ||
1a511d31 | 288 | static void |
11336c16 | 289 | rfg2 (void) |
28f540f4 RM |
290 | { |
291 | int prec; | |
292 | char buf[100]; | |
293 | ||
294 | prec = 0; | |
295 | sprintf (buf, "%.*g", prec, 3.3); | |
296 | if (strcmp (buf, "3") != 0) | |
297 | printf ("got: '%s', expected: '%s'\n", buf, "3"); | |
298 | prec = 0; | |
299 | sprintf (buf, "%.*G", prec, 3.3); | |
300 | if (strcmp (buf, "3") != 0) | |
301 | printf ("got: '%s', expected: '%s'\n", buf, "3"); | |
302 | prec = 0; | |
303 | sprintf (buf, "%7.*G", prec, 3.33); | |
304 | if (strcmp (buf, " 3") != 0) | |
305 | printf ("got: '%s', expected: '%s'\n", buf, " 3"); | |
306 | prec = 3; | |
307 | sprintf (buf, "%04.*o", prec, 33); | |
308 | if (strcmp (buf, " 041") != 0) | |
309 | printf ("got: '%s', expected: '%s'\n", buf, " 041"); | |
310 | prec = 7; | |
311 | sprintf (buf, "%09.*u", prec, 33); | |
312 | if (strcmp (buf, " 0000033") != 0) | |
313 | printf ("got: '%s', expected: '%s'\n", buf, " 0000033"); | |
314 | prec = 3; | |
315 | sprintf (buf, "%04.*x", prec, 33); | |
316 | if (strcmp (buf, " 021") != 0) | |
317 | printf ("got: '%s', expected: '%s'\n", buf, " 021"); | |
318 | prec = 3; | |
319 | sprintf (buf, "%04.*X", prec, 33); | |
320 | if (strcmp (buf, " 021") != 0) | |
321 | printf ("got: '%s', expected: '%s'\n", buf, " 021"); | |
28f540f4 | 322 | } |
75bfdfc7 UD |
323 | |
324 | static void | |
325 | rfg3 (void) | |
326 | { | |
327 | char buf[100]; | |
328 | double g = 5.0000001; | |
329 | unsigned long l = 1234567890; | |
330 | double d = 321.7654321; | |
c06b947e | 331 | const char s[] = "test-string"; |
75bfdfc7 UD |
332 | int i = 12345; |
333 | int h = 1234; | |
334 | ||
335 | sprintf (buf, | |
336 | "%1$*5$d %2$*6$hi %3$*7$lo %4$*8$f %9$*12$e %10$*13$g %11$*14$s", | |
337 | i, h, l, d, 8, 5, 14, 14, d, g, s, 14, 3, 14); | |
338 | if (strcmp (buf, | |
339 | " 12345 1234 11145401322 321.765432 3.217654e+02 5 test-string") != 0) | |
340 | printf ("got: '%s', expected: '%s'\n", buf, | |
341 | " 12345 1234 11145401322 321.765432 3.217654e+02 5 test-string"); | |
342 | } | |
c1f41083 AS |
343 | |
344 | #define TEST_FUNCTION do_test () | |
345 | #include "../test-skeleton.c" |