1/*
2 * Copyright (c) 2000 - 2001 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
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 *
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of KTH nor the names of its contributors may be
18 *    used to endorse or promote products derived from this software without
19 *    specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
32
33#include <config.h>
34#include "roken.h"
35#include <limits.h>
36
37static int
38try (const char *format, ...)
39{
40    int ret;
41    va_list ap;
42    char buf1[256], buf2[256];
43
44    va_start (ap, format);
45    ret = rk_vsnprintf (buf1, sizeof(buf1), format, ap);
46    if (ret >= sizeof(buf1))
47	errx (1, "increase buf and try again");
48    va_end (ap);
49    va_start (ap, format);
50    vsprintf (buf2, format, ap);
51    ret = strcmp (buf1, buf2);
52    if (ret)
53	printf ("failed: format = \"%s\", \"%s\" != \"%s\"\n",
54		format, buf1, buf2);
55    va_end (ap);
56    return ret;
57}
58
59static int
60cmp_with_sprintf_int (void)
61{
62    int tot = 0;
63    int int_values[] = {INT_MIN, -17, -1, 0, 1, 17, 4711, 65535, INT_MAX};
64    int i;
65
66    for (i = 0; i < sizeof(int_values) / sizeof(int_values[0]); ++i) {
67	tot += try ("%d", int_values[i]);
68	tot += try ("%x", int_values[i]);
69	tot += try ("%X", int_values[i]);
70	tot += try ("%o", int_values[i]);
71	tot += try ("%#x", int_values[i]);
72	tot += try ("%#X", int_values[i]);
73	tot += try ("%#o", int_values[i]);
74	tot += try ("%10d", int_values[i]);
75	tot += try ("%10x", int_values[i]);
76	tot += try ("%10X", int_values[i]);
77	tot += try ("%10o", int_values[i]);
78	tot += try ("%#10x", int_values[i]);
79	tot += try ("%#10X", int_values[i]);
80	tot += try ("%#10o", int_values[i]);
81	tot += try ("%-10d", int_values[i]);
82	tot += try ("%-10x", int_values[i]);
83	tot += try ("%-10X", int_values[i]);
84	tot += try ("%-10o", int_values[i]);
85	tot += try ("%-#10x", int_values[i]);
86	tot += try ("%-#10X", int_values[i]);
87	tot += try ("%-#10o", int_values[i]);
88    }
89    return tot;
90}
91
92static int
93cmp_with_sprintf_long (void)
94{
95    int tot = 0;
96    long long_values[] = {LONG_MIN, -17, -1, 0, 1, 17, 4711, 65535, LONG_MAX};
97    int i;
98
99    for (i = 0; i < sizeof(long_values) / sizeof(long_values[0]); ++i) {
100	tot += try ("%ld", long_values[i]);
101	tot += try ("%lx", long_values[i]);
102	tot += try ("%lX", long_values[i]);
103	tot += try ("%lo", long_values[i]);
104	tot += try ("%#lx", long_values[i]);
105	tot += try ("%#lX", long_values[i]);
106	tot += try ("%#lo", long_values[i]);
107	tot += try ("%10ld", long_values[i]);
108	tot += try ("%10lx", long_values[i]);
109	tot += try ("%10lX", long_values[i]);
110	tot += try ("%10lo", long_values[i]);
111	tot += try ("%#10lx", long_values[i]);
112	tot += try ("%#10lX", long_values[i]);
113	tot += try ("%#10lo", long_values[i]);
114	tot += try ("%-10ld", long_values[i]);
115	tot += try ("%-10lx", long_values[i]);
116	tot += try ("%-10lX", long_values[i]);
117	tot += try ("%-10lo", long_values[i]);
118	tot += try ("%-#10lx", long_values[i]);
119	tot += try ("%-#10lX", long_values[i]);
120	tot += try ("%-#10lo", long_values[i]);
121    }
122    return tot;
123}
124
125#ifdef HAVE_LONG_LONG
126
127/* XXX doesn't work as expected on lp64 platforms with sizeof(long
128 * long) == sizeof(long) */
129
130static int
131cmp_with_sprintf_long_long (void)
132{
133    int tot = 0;
134    long long long_long_values[] = {
135	((long long)LONG_MIN) -1, LONG_MIN, -17, -1,
136	0,
137	1, 17, 4711, 65535, LONG_MAX, ((long long)LONG_MAX) + 1};
138    int i;
139
140    for (i = 0; i < sizeof(long_long_values) / sizeof(long_long_values[0]); ++i) {
141	tot += try ("%lld", long_long_values[i]);
142	tot += try ("%llx", long_long_values[i]);
143	tot += try ("%llX", long_long_values[i]);
144	tot += try ("%llo", long_long_values[i]);
145	tot += try ("%#llx", long_long_values[i]);
146	tot += try ("%#llX", long_long_values[i]);
147	tot += try ("%#llo", long_long_values[i]);
148	tot += try ("%10lld", long_long_values[i]);
149	tot += try ("%10llx", long_long_values[i]);
150	tot += try ("%10llX", long_long_values[i]);
151	tot += try ("%10llo", long_long_values[i]);
152	tot += try ("%#10llx", long_long_values[i]);
153	tot += try ("%#10llX", long_long_values[i]);
154	tot += try ("%#10llo", long_long_values[i]);
155	tot += try ("%-10lld", long_long_values[i]);
156	tot += try ("%-10llx", long_long_values[i]);
157	tot += try ("%-10llX", long_long_values[i]);
158	tot += try ("%-10llo", long_long_values[i]);
159	tot += try ("%-#10llx", long_long_values[i]);
160	tot += try ("%-#10llX", long_long_values[i]);
161	tot += try ("%-#10llo", long_long_values[i]);
162    }
163    return tot;
164}
165
166#endif
167
168#if 0
169static int
170cmp_with_sprintf_float (void)
171{
172    int tot = 0;
173    double double_values[] = {-99999, -999, -17.4, -4.3, -3.0, -1.5, -1,
174			      0, 0.1, 0.2342374852, 0.2340007,
175			      3.1415926, 14.7845, 34.24758, 9999, 9999999};
176    int i;
177
178    for (i = 0; i < sizeof(double_values) / sizeof(double_values[0]); ++i) {
179	tot += try ("%f", double_values[i]);
180	tot += try ("%10f", double_values[i]);
181	tot += try ("%.2f", double_values[i]);
182	tot += try ("%7.0f", double_values[i]);
183	tot += try ("%5.2f", double_values[i]);
184	tot += try ("%0f", double_values[i]);
185	tot += try ("%#f", double_values[i]);
186	tot += try ("%e", double_values[i]);
187	tot += try ("%10e", double_values[i]);
188	tot += try ("%.2e", double_values[i]);
189	tot += try ("%7.0e", double_values[i]);
190	tot += try ("%5.2e", double_values[i]);
191	tot += try ("%0e", double_values[i]);
192	tot += try ("%#e", double_values[i]);
193	tot += try ("%E", double_values[i]);
194	tot += try ("%10E", double_values[i]);
195	tot += try ("%.2E", double_values[i]);
196	tot += try ("%7.0E", double_values[i]);
197	tot += try ("%5.2E", double_values[i]);
198	tot += try ("%0E", double_values[i]);
199	tot += try ("%#E", double_values[i]);
200	tot += try ("%g", double_values[i]);
201	tot += try ("%10g", double_values[i]);
202	tot += try ("%.2g", double_values[i]);
203	tot += try ("%7.0g", double_values[i]);
204	tot += try ("%5.2g", double_values[i]);
205	tot += try ("%0g", double_values[i]);
206	tot += try ("%#g", double_values[i]);
207	tot += try ("%G", double_values[i]);
208	tot += try ("%10G", double_values[i]);
209	tot += try ("%.2G", double_values[i]);
210	tot += try ("%7.0G", double_values[i]);
211	tot += try ("%5.2G", double_values[i]);
212	tot += try ("%0G", double_values[i]);
213	tot += try ("%#G", double_values[i]);
214    }
215    return tot;
216}
217#endif
218
219static int
220test_null (void)
221{
222    return rk_snprintf (NULL, 0, "foo") != 3;
223}
224
225static int
226test_sizet (void)
227{
228    int tot = 0;
229    size_t sizet_values[] = { 0, 1, 2, 200, 4294967295u }; /* SIZE_MAX */
230    char *result[] = { "0", "1", "2", "200", "4294967295" };
231    int i;
232
233    for (i = 0; i < sizeof(sizet_values) / sizeof(sizet_values[0]); ++i) {
234#if 0
235	tot += try("%zu", sizet_values[i]);
236	tot += try("%zx", sizet_values[i]);
237	tot += try("%zX", sizet_values[i]);
238#else
239	char buf[256];
240	rk_snprintf(buf, sizeof(buf), "%zu", sizet_values[i]);
241	if (strcmp(buf, result[i]) != 0) {
242	    printf("%s != %s", buf, result[i]);
243	    tot++;
244	}
245#endif
246    }
247    return tot;
248}
249
250
251int
252main (int argc, char **argv)
253{
254    int ret = 0;
255
256    ret += cmp_with_sprintf_int ();
257    ret += cmp_with_sprintf_long ();
258#ifdef HAVE_LONG_LONG
259    ret += cmp_with_sprintf_long_long ();
260#endif
261    ret += test_null ();
262    ret += test_sizet ();
263    return ret;
264}
265