190926Snectar/*
2233294Sstas * Copyright (c) 2000 - 2001 Kungliga Tekniska H��gskolan
3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4233294Sstas * All rights reserved.
590926Snectar *
6233294Sstas * Redistribution and use in source and binary forms, with or without
7233294Sstas * modification, are permitted provided that the following conditions
8233294Sstas * are met:
990926Snectar *
10233294Sstas * 1. Redistributions of source code must retain the above copyright
11233294Sstas *    notice, this list of conditions and the following disclaimer.
1290926Snectar *
13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright
14233294Sstas *    notice, this list of conditions and the following disclaimer in the
15233294Sstas *    documentation and/or other materials provided with the distribution.
1690926Snectar *
1790926Snectar * 3. Neither the name of KTH nor the names of its contributors may be
1890926Snectar *    used to endorse or promote products derived from this software without
1990926Snectar *    specific prior written permission.
2090926Snectar *
2190926Snectar * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
2290926Snectar * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2390926Snectar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2490926Snectar * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
2590926Snectar * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2690926Snectar * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2790926Snectar * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
2890926Snectar * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2990926Snectar * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
3090926Snectar * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
3190926Snectar * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
3290926Snectar
3390926Snectar#include <config.h>
3490926Snectar#include "roken.h"
3590926Snectar#include <limits.h>
3690926Snectar
3790926Snectarstatic int
3890926Snectartry (const char *format, ...)
3990926Snectar{
4090926Snectar    int ret;
4190926Snectar    va_list ap;
4290926Snectar    char buf1[256], buf2[256];
4390926Snectar
4490926Snectar    va_start (ap, format);
45233294Sstas    ret = rk_vsnprintf (buf1, sizeof(buf1), format, ap);
4690926Snectar    if (ret >= sizeof(buf1))
4790926Snectar	errx (1, "increase buf and try again");
48178825Sdfr    va_end (ap);
49178825Sdfr    va_start (ap, format);
5090926Snectar    vsprintf (buf2, format, ap);
5190926Snectar    ret = strcmp (buf1, buf2);
5290926Snectar    if (ret)
5390926Snectar	printf ("failed: format = \"%s\", \"%s\" != \"%s\"\n",
5490926Snectar		format, buf1, buf2);
5590926Snectar    va_end (ap);
5690926Snectar    return ret;
5790926Snectar}
5890926Snectar
5990926Snectarstatic int
6090926Snectarcmp_with_sprintf_int (void)
6190926Snectar{
6290926Snectar    int tot = 0;
6390926Snectar    int int_values[] = {INT_MIN, -17, -1, 0, 1, 17, 4711, 65535, INT_MAX};
6490926Snectar    int i;
6590926Snectar
6690926Snectar    for (i = 0; i < sizeof(int_values) / sizeof(int_values[0]); ++i) {
6790926Snectar	tot += try ("%d", int_values[i]);
6890926Snectar	tot += try ("%x", int_values[i]);
6990926Snectar	tot += try ("%X", int_values[i]);
7090926Snectar	tot += try ("%o", int_values[i]);
7190926Snectar	tot += try ("%#x", int_values[i]);
7290926Snectar	tot += try ("%#X", int_values[i]);
7390926Snectar	tot += try ("%#o", int_values[i]);
7490926Snectar	tot += try ("%10d", int_values[i]);
7590926Snectar	tot += try ("%10x", int_values[i]);
7690926Snectar	tot += try ("%10X", int_values[i]);
7790926Snectar	tot += try ("%10o", int_values[i]);
7890926Snectar	tot += try ("%#10x", int_values[i]);
7990926Snectar	tot += try ("%#10X", int_values[i]);
8090926Snectar	tot += try ("%#10o", int_values[i]);
8190926Snectar	tot += try ("%-10d", int_values[i]);
8290926Snectar	tot += try ("%-10x", int_values[i]);
8390926Snectar	tot += try ("%-10X", int_values[i]);
8490926Snectar	tot += try ("%-10o", int_values[i]);
8590926Snectar	tot += try ("%-#10x", int_values[i]);
8690926Snectar	tot += try ("%-#10X", int_values[i]);
8790926Snectar	tot += try ("%-#10o", int_values[i]);
8890926Snectar    }
8990926Snectar    return tot;
9090926Snectar}
9190926Snectar
9290926Snectarstatic int
9390926Snectarcmp_with_sprintf_long (void)
9490926Snectar{
9590926Snectar    int tot = 0;
9690926Snectar    long long_values[] = {LONG_MIN, -17, -1, 0, 1, 17, 4711, 65535, LONG_MAX};
9790926Snectar    int i;
9890926Snectar
9990926Snectar    for (i = 0; i < sizeof(long_values) / sizeof(long_values[0]); ++i) {
10090926Snectar	tot += try ("%ld", long_values[i]);
10190926Snectar	tot += try ("%lx", long_values[i]);
10290926Snectar	tot += try ("%lX", long_values[i]);
10390926Snectar	tot += try ("%lo", long_values[i]);
10490926Snectar	tot += try ("%#lx", long_values[i]);
10590926Snectar	tot += try ("%#lX", long_values[i]);
10690926Snectar	tot += try ("%#lo", long_values[i]);
10790926Snectar	tot += try ("%10ld", long_values[i]);
10890926Snectar	tot += try ("%10lx", long_values[i]);
10990926Snectar	tot += try ("%10lX", long_values[i]);
11090926Snectar	tot += try ("%10lo", long_values[i]);
11190926Snectar	tot += try ("%#10lx", long_values[i]);
11290926Snectar	tot += try ("%#10lX", long_values[i]);
11390926Snectar	tot += try ("%#10lo", long_values[i]);
11490926Snectar	tot += try ("%-10ld", long_values[i]);
11590926Snectar	tot += try ("%-10lx", long_values[i]);
11690926Snectar	tot += try ("%-10lX", long_values[i]);
11790926Snectar	tot += try ("%-10lo", long_values[i]);
11890926Snectar	tot += try ("%-#10lx", long_values[i]);
11990926Snectar	tot += try ("%-#10lX", long_values[i]);
12090926Snectar	tot += try ("%-#10lo", long_values[i]);
12190926Snectar    }
12290926Snectar    return tot;
12390926Snectar}
12490926Snectar
12590926Snectar#ifdef HAVE_LONG_LONG
12690926Snectar
127178825Sdfr/* XXX doesn't work as expected on lp64 platforms with sizeof(long
128178825Sdfr * long) == sizeof(long) */
129178825Sdfr
13090926Snectarstatic int
13190926Snectarcmp_with_sprintf_long_long (void)
13290926Snectar{
13390926Snectar    int tot = 0;
13490926Snectar    long long long_long_values[] = {
13590926Snectar	((long long)LONG_MIN) -1, LONG_MIN, -17, -1,
13690926Snectar	0,
13790926Snectar	1, 17, 4711, 65535, LONG_MAX, ((long long)LONG_MAX) + 1};
13890926Snectar    int i;
13990926Snectar
14090926Snectar    for (i = 0; i < sizeof(long_long_values) / sizeof(long_long_values[0]); ++i) {
14190926Snectar	tot += try ("%lld", long_long_values[i]);
14290926Snectar	tot += try ("%llx", long_long_values[i]);
14390926Snectar	tot += try ("%llX", long_long_values[i]);
14490926Snectar	tot += try ("%llo", long_long_values[i]);
14590926Snectar	tot += try ("%#llx", long_long_values[i]);
14690926Snectar	tot += try ("%#llX", long_long_values[i]);
14790926Snectar	tot += try ("%#llo", long_long_values[i]);
14890926Snectar	tot += try ("%10lld", long_long_values[i]);
14990926Snectar	tot += try ("%10llx", long_long_values[i]);
15090926Snectar	tot += try ("%10llX", long_long_values[i]);
15190926Snectar	tot += try ("%10llo", long_long_values[i]);
15290926Snectar	tot += try ("%#10llx", long_long_values[i]);
15390926Snectar	tot += try ("%#10llX", long_long_values[i]);
15490926Snectar	tot += try ("%#10llo", long_long_values[i]);
15590926Snectar	tot += try ("%-10lld", long_long_values[i]);
15690926Snectar	tot += try ("%-10llx", long_long_values[i]);
15790926Snectar	tot += try ("%-10llX", long_long_values[i]);
15890926Snectar	tot += try ("%-10llo", long_long_values[i]);
15990926Snectar	tot += try ("%-#10llx", long_long_values[i]);
16090926Snectar	tot += try ("%-#10llX", long_long_values[i]);
16190926Snectar	tot += try ("%-#10llo", long_long_values[i]);
16290926Snectar    }
16390926Snectar    return tot;
16490926Snectar}
16590926Snectar
16690926Snectar#endif
16790926Snectar
16890926Snectar#if 0
16990926Snectarstatic int
17090926Snectarcmp_with_sprintf_float (void)
17190926Snectar{
17290926Snectar    int tot = 0;
17390926Snectar    double double_values[] = {-99999, -999, -17.4, -4.3, -3.0, -1.5, -1,
17490926Snectar			      0, 0.1, 0.2342374852, 0.2340007,
17590926Snectar			      3.1415926, 14.7845, 34.24758, 9999, 9999999};
17690926Snectar    int i;
17790926Snectar
17890926Snectar    for (i = 0; i < sizeof(double_values) / sizeof(double_values[0]); ++i) {
17990926Snectar	tot += try ("%f", double_values[i]);
18090926Snectar	tot += try ("%10f", double_values[i]);
18190926Snectar	tot += try ("%.2f", double_values[i]);
18290926Snectar	tot += try ("%7.0f", double_values[i]);
18390926Snectar	tot += try ("%5.2f", double_values[i]);
18490926Snectar	tot += try ("%0f", double_values[i]);
18590926Snectar	tot += try ("%#f", double_values[i]);
18690926Snectar	tot += try ("%e", double_values[i]);
18790926Snectar	tot += try ("%10e", double_values[i]);
18890926Snectar	tot += try ("%.2e", double_values[i]);
18990926Snectar	tot += try ("%7.0e", double_values[i]);
19090926Snectar	tot += try ("%5.2e", double_values[i]);
19190926Snectar	tot += try ("%0e", double_values[i]);
19290926Snectar	tot += try ("%#e", double_values[i]);
19390926Snectar	tot += try ("%E", double_values[i]);
19490926Snectar	tot += try ("%10E", double_values[i]);
19590926Snectar	tot += try ("%.2E", double_values[i]);
19690926Snectar	tot += try ("%7.0E", double_values[i]);
19790926Snectar	tot += try ("%5.2E", double_values[i]);
19890926Snectar	tot += try ("%0E", double_values[i]);
19990926Snectar	tot += try ("%#E", double_values[i]);
20090926Snectar	tot += try ("%g", double_values[i]);
20190926Snectar	tot += try ("%10g", double_values[i]);
20290926Snectar	tot += try ("%.2g", double_values[i]);
20390926Snectar	tot += try ("%7.0g", double_values[i]);
20490926Snectar	tot += try ("%5.2g", double_values[i]);
20590926Snectar	tot += try ("%0g", double_values[i]);
20690926Snectar	tot += try ("%#g", double_values[i]);
20790926Snectar	tot += try ("%G", double_values[i]);
20890926Snectar	tot += try ("%10G", double_values[i]);
20990926Snectar	tot += try ("%.2G", double_values[i]);
21090926Snectar	tot += try ("%7.0G", double_values[i]);
21190926Snectar	tot += try ("%5.2G", double_values[i]);
21290926Snectar	tot += try ("%0G", double_values[i]);
21390926Snectar	tot += try ("%#G", double_values[i]);
21490926Snectar    }
21590926Snectar    return tot;
21690926Snectar}
21790926Snectar#endif
21890926Snectar
21990926Snectarstatic int
22090926Snectartest_null (void)
22190926Snectar{
222233294Sstas    return rk_snprintf (NULL, 0, "foo") != 3;
22390926Snectar}
22490926Snectar
225178825Sdfrstatic int
226178825Sdfrtest_sizet (void)
227178825Sdfr{
228178825Sdfr    int tot = 0;
229178825Sdfr    size_t sizet_values[] = { 0, 1, 2, 200, 4294967295u }; /* SIZE_MAX */
230178825Sdfr    char *result[] = { "0", "1", "2", "200", "4294967295" };
231178825Sdfr    int i;
232178825Sdfr
233178825Sdfr    for (i = 0; i < sizeof(sizet_values) / sizeof(sizet_values[0]); ++i) {
234178825Sdfr#if 0
235178825Sdfr	tot += try("%zu", sizet_values[i]);
236178825Sdfr	tot += try("%zx", sizet_values[i]);
237178825Sdfr	tot += try("%zX", sizet_values[i]);
238178825Sdfr#else
239178825Sdfr	char buf[256];
240233294Sstas	rk_snprintf(buf, sizeof(buf), "%zu", sizet_values[i]);
241178825Sdfr	if (strcmp(buf, result[i]) != 0) {
242178825Sdfr	    printf("%s != %s", buf, result[i]);
243178825Sdfr	    tot++;
244178825Sdfr	}
245178825Sdfr#endif
246178825Sdfr    }
247178825Sdfr    return tot;
248178825Sdfr}
249178825Sdfr
250178825Sdfr
25190926Snectarint
25290926Snectarmain (int argc, char **argv)
25390926Snectar{
25490926Snectar    int ret = 0;
25590926Snectar
25690926Snectar    ret += cmp_with_sprintf_int ();
25790926Snectar    ret += cmp_with_sprintf_long ();
25890926Snectar#ifdef HAVE_LONG_LONG
25990926Snectar    ret += cmp_with_sprintf_long_long ();
26090926Snectar#endif
26190926Snectar    ret += test_null ();
262178825Sdfr    ret += test_sizet ();
26390926Snectar    return ret;
26490926Snectar}
265