1 /*
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright © 2023 Keith Packard
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
14  *    copyright notice, this list of conditions and the following
15  *    disclaimer in the documentation and/or other materials provided
16  *    with the distribution.
17  *
18  * 3. Neither the name of the copyright holder nor the names of its
19  *    contributors may be used to endorse or promote products derived
20  *    from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33  * OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #define _GNU_SOURCE
37 #include <stdbool.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <assert.h>
42 
43 #if !defined(__PICOLIBC__) || defined(TINY_STDIO) || defined(_WANT_IO_LONG_LONG)
44 
45 #if 0
46 static unsigned long long
47 naive_atou(const char *buf)
48 {
49     unsigned long long v = 0;
50     int sign = 1;
51     char c;
52 
53     while ((c = *buf++) == ' ')
54         ;
55     do {
56         assert('0' <= c && c <= '9');
57         v = v * 10 + (c - '0');
58         c = *buf++;
59     } while(c);
60     return v * sign;
61 }
62 
63 static long long
64 naive_atol(const char *buf)
65 {
66     long long v = 0;
67     int sign = 1;
68     char c;
69 
70     while ((c = *buf++) == ' ')
71         ;
72     switch (c) {
73     case '+':
74         sign = 1;
75         c = *buf++;
76         break;
77     case '-':
78         sign = -1;
79         c = *buf++;
80         break;
81     }
82     do {
83         assert('0' <= c && c <= '9');
84         v = v * 10 + (c - '0');
85         c = *buf++;
86     } while(c);
87     return v * sign;
88 }
89 #endif
90 
91 static char *
naive_utoa(char * buf,unsigned long long v)92 naive_utoa(char *buf, unsigned long long v)
93 {
94     buf += 21;
95     *--buf = '\0';
96     do {
97         *--buf = v % 10 + '0';
98         v /= 10;
99     } while (v);
100     return buf;
101 }
102 
103 static char *
naive_ltoa(char * buf,long long v)104 naive_ltoa(char *buf, long long v)
105 {
106     int sign = 0;
107     buf += 21;
108     *--buf = '\0';
109     if (v < 0) {
110         sign = 1;
111         v = -v;
112     }
113     do {
114         *--buf = v % 10 + '0';
115         v /= 10;
116     } while (v);
117     if (sign)
118         *--buf = '-';
119     return buf;
120 }
121 
122 static int
check(long long x)123 check(long long x)
124 {
125     long long   scanned, uscanned, u;
126     char        buf[64], naive_buf[64];
127     char        *naive;
128     int         ret = 0;
129 
130     sprintf(buf, "%lld", x);
131     naive = naive_ltoa(naive_buf, x);
132     sscanf(naive, "%lld", &scanned);
133     if (strcmp(buf, naive) != 0) {
134         printf("sprintf '%s' naive '%s'\n", buf, naive);
135         ret = 1;
136     }
137     if (scanned != x) {
138         printf("sscanf '%lld' actual '%lld'\n", scanned, x);
139         ret = 1;
140     }
141 
142     u = (unsigned long long) x;
143     sprintf(buf, "%llu", u);
144     naive = naive_utoa(naive_buf, u);
145     sscanf(naive, "%llu", &uscanned);
146     if (strcmp(buf, naive) != 0) {
147         printf("unsigned sprintf '%s' naive '%s'\n", buf, naive);
148         ret = 1;
149     }
150     if (scanned != x) {
151         printf("unsigned sscanf '%llu' actual '%llu'\n", uscanned, u);
152         ret = 1;
153     }
154     return ret;
155 }
156 
157 static long long
randval(void)158 randval(void)
159 {
160     unsigned long        a, b, c;
161 
162     a = random();
163     b = random();
164     c = random();
165     return ((unsigned long long) a << 33) ^ ((unsigned long long) b << 15) ^ ((unsigned long long) c);
166 }
167 
168 #ifdef __MSP430__
169 #define RAND_LOOPS 1000ll
170 #define SMALL_MIN -1024ll
171 #define SMALL_MAX 1024ll
172 #else
173 #define RAND_LOOPS 100000ll
174 #define SMALL_MIN -65536
175 #define SMALL_MAX 65536
176 #endif
177 
main(void)178 int main(void)
179 {
180     long long   x;
181     int         ret = 0;
182     long long   t;
183 
184     for (x = SMALL_MIN; x <= SMALL_MAX; x++)
185         ret |= check(x);
186 
187     for (t = 0; t < RAND_LOOPS; t++) {
188         x = randval();
189         ret |= check(x);
190     }
191     return ret;
192 }
193 
194 #else
195 
main(void)196 int main(void)
197 {
198     printf("skipping long long I/O test\n");
199     return 77;
200 }
201 
202 #endif
203