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