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 unsigned long long
naive_atou(const char * buf)46 naive_atou(const char *buf)
47 {
48 unsigned long long v = 0;
49 int sign = 1;
50 char c;
51
52 while ((c = *buf++) == ' ')
53 ;
54 do {
55 assert('0' <= c && c <= '9');
56 v = v * 10 + (c - '0');
57 c = *buf++;
58 } while(c);
59 return v * sign;
60 }
61
62 long long
naive_atol(const char * buf)63 naive_atol(const char *buf)
64 {
65 long long v = 0;
66 int sign = 1;
67 char c;
68
69 while ((c = *buf++) == ' ')
70 ;
71 switch (c) {
72 case '+':
73 sign = 1;
74 c = *buf++;
75 break;
76 case '-':
77 sign = -1;
78 c = *buf++;
79 break;
80 }
81 do {
82 assert('0' <= c && c <= '9');
83 v = v * 10 + (c - '0');
84 c = *buf++;
85 } while(c);
86 return v * sign;
87 }
88
89 char *
naive_utoa(char * buf,unsigned long long v)90 naive_utoa(char *buf, unsigned long long v)
91 {
92 buf += 21;
93 *--buf = '\0';
94 do {
95 *--buf = v % 10 + '0';
96 v /= 10;
97 } while (v);
98 return buf;
99 }
100
101 char *
naive_ltoa(char * buf,long long v)102 naive_ltoa(char *buf, long long v)
103 {
104 int sign = 0;
105 buf += 21;
106 *--buf = '\0';
107 if (v < 0) {
108 sign = 1;
109 v = -v;
110 }
111 do {
112 *--buf = v % 10 + '0';
113 v /= 10;
114 } while (v);
115 if (sign)
116 *--buf = '-';
117 return buf;
118 }
119
120 static int
check(long long x)121 check(long long x)
122 {
123 long long scanned, uscanned, u;
124 char buf[64], naive_buf[64];
125 char *naive;
126 int ret = 0;
127
128 sprintf(buf, "%lld", x);
129 naive = naive_ltoa(naive_buf, x);
130 sscanf(naive, "%lld", &scanned);
131 if (strcmp(buf, naive) != 0) {
132 printf("sprintf '%s' naive '%s'\n", buf, naive);
133 ret = 1;
134 }
135 if (scanned != x) {
136 printf("sscanf '%lld' actual '%lld'\n", scanned, x);
137 ret = 1;
138 }
139
140 u = (unsigned long long) x;
141 sprintf(buf, "%llu", u);
142 naive = naive_utoa(naive_buf, u);
143 sscanf(naive, "%llu", &uscanned);
144 if (strcmp(buf, naive) != 0) {
145 printf("unsigned sprintf '%s' naive '%s'\n", buf, naive);
146 ret = 1;
147 }
148 if (scanned != x) {
149 printf("unsigned sscanf '%llu' actual '%llu'\n", uscanned, u);
150 ret = 1;
151 }
152 return ret;
153 }
154
155 static long long
randval(void)156 randval(void)
157 {
158 unsigned long a, b, c;
159
160 a = random();
161 b = random();
162 c = random();
163 return ((unsigned long long) a << 33) ^ ((unsigned long long) b << 15) ^ ((unsigned long long) c);
164 }
165
166 #ifdef __MSP430__
167 #define RAND_LOOPS 1000ll
168 #define SMALL_MIN -1024ll
169 #define SMALL_MAX 1024ll
170 #else
171 #define RAND_LOOPS 100000ll
172 #define SMALL_MIN -65536
173 #define SMALL_MAX 65536
174 #endif
175
main(void)176 int main(void)
177 {
178 long long x;
179 int ret = 0;
180 long long t;
181
182 for (x = SMALL_MIN; x <= SMALL_MAX; x++)
183 ret |= check(x);
184
185 for (t = 0; t < RAND_LOOPS; t++) {
186 x = randval();
187 ret |= check(x);
188 }
189 return ret;
190 }
191
192 #else
193
main(void)194 int main(void)
195 {
196 printf("skipping long long I/O test\n");
197 return 77;
198 }
199
200 #endif
201