1 /* Copyright © 2013 Bart Massey */
2 /* This program is licensed under the GPL version 2 or later.
3 Please see the file COPYING.GPL2 in this distribution for
4 license terms. */
5
6 #define _GNU_SOURCE
7 #include <stdio.h>
8 #include <stdarg.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <stdint.h>
12 #include <math.h>
13 #include <wchar.h>
14
15 #ifndef TINY_STDIO
16 #define printf_float(x) x
17 #ifdef _NANO_FORMATTED_IO
18 #ifndef NO_FLOATING_POINT
19 extern int _printf_float();
20 extern int _scanf_float();
21
22 int (*_reference_printf_float)() = _printf_float;
23 int (*_reference_scanf_float)() = _scanf_float;
24 #define TEST_ASPRINTF
25 #endif
26 #endif
27 #endif
28
29 static char buf[1024];
30 static wchar_t wbuf[1024];
31
failmsg(int serial,char * fmt,...)32 static void failmsg(int serial, char *fmt, ...) {
33 va_list ap;
34 va_start(ap, fmt);
35 printf("test %d failed: ", serial);
36 vprintf(fmt, ap);
37 printf("\n");
38 va_end(ap);
39 }
40
test(int serial,char * expect,char * fmt,...)41 static int test(int serial, char *expect, char *fmt, ...) {
42 va_list ap;
43 char *abuf = NULL;
44 va_start(ap, fmt);
45 int n;
46 #ifdef TEST_ASPRINTF
47 int an;
48 va_list aap;
49 va_copy(aap, ap);
50 #endif
51 #ifndef NO_FLOATING_POINT
52 double dv;
53 char *star;
54 #endif
55 switch (fmt[strlen(fmt)-1]) {
56 case 'e':
57 case 'E':
58 case 'f':
59 case 'F':
60 case 'g':
61 case 'G':
62 case 'a':
63 case 'A':
64 #ifdef NO_FLOATING_POINT
65 return 0;
66 #else
67 star = strchr(fmt, '*');
68 if (star) {
69 if (strchr(star+1, '*')) {
70 int iv1 = va_arg(ap, int);
71 int iv2 = va_arg(ap, int);
72 dv = va_arg(ap, double);
73 n = snprintf(buf, 1024, fmt, iv1, iv2, printf_float(dv));
74 #ifdef TEST_ASPRINTF
75 an = asprintf(&abuf, fmt, iv1, iv2, printf_float(dv));
76 #endif
77 } else {
78 int iv = va_arg(ap, int);
79 dv = va_arg(ap, double);
80 n = snprintf(buf, 1024, fmt, iv, printf_float(dv));
81 #ifdef TEST_ASPRINTF
82 an = asprintf(&abuf, fmt, iv, printf_float(dv));
83 #endif
84 }
85 } else {
86 dv = va_arg(ap, double);
87 n = snprintf(buf, 1024, fmt, printf_float(dv));
88 #ifdef TEST_ASPRINTF
89 an = asprintf(&abuf, fmt, printf_float(dv));
90 #endif
91 }
92 break;
93 #endif
94 default:
95 n = vsnprintf(buf, 1024, fmt, ap);
96 #ifdef TEST_ASPRINTF
97 an = vasprintf(&abuf, fmt, aap);
98 #endif
99 break;
100 }
101 va_end(ap);
102 #ifdef TEST_ASPRINTF
103 va_end(aap);
104 #endif
105 // printf("serial %d expect \"%s\" got \"%s\"\n", serial, expect, buf);
106 if (n >= 1024) {
107 failmsg(serial, "buffer overflow");
108 free(abuf);
109 return 1;
110 }
111 if (n != (int) strlen(expect)) {
112 failmsg(serial, "expected \"%s\" (%d), got \"%s\" (%d)",
113 expect, strlen(expect), buf, n);
114 free(abuf);
115 return 1;
116 }
117 if (strcmp(buf, expect)) {
118 failmsg(serial, "expected \"%s\", got \"%s\"", expect, buf);
119 free(abuf);
120 return 1;
121 }
122 #ifdef TEST_ASPRINTF
123 if (an != n) {
124 failmsg(serial, "asprintf return %d sprintf return %d\n", an, n);
125 free(abuf);
126 return 1;
127 }
128 if (strcmp(abuf, buf)) {
129 failmsg(serial, "sprintf return %s asprintf return %s\n", buf, abuf);
130 free(abuf);
131 return 1;
132 }
133 free(abuf);
134 #endif
135 return 0;
136 }
137
failmsgw(int serial,wchar_t * fmt,...)138 static void failmsgw(int serial, wchar_t *fmt, ...) {
139 va_list ap;
140 va_start(ap, fmt);
141 printf("test %d failed: ", serial);
142 static wchar_t f_wbuf[1024];
143 static char f_buf[1024];
144 vswprintf(f_wbuf, 1024, fmt, ap);
145 wcstombs(f_buf, f_wbuf, 1024);
146 printf("%s\n", f_buf);
147 va_end(ap);
148 }
149
testw(int serial,wchar_t * expect,wchar_t * fmt,...)150 static int testw(int serial, wchar_t *expect, wchar_t *fmt, ...) {
151 va_list ap;
152 wchar_t *abuf = NULL;
153 va_start(ap, fmt);
154 int n;
155 #ifdef TEST_ASPRINTF
156 int an;
157 va_list aap;
158 va_copy(aap, ap);
159 #endif
160 #ifndef NO_FLOATING_POINT
161 double dv;
162 wchar_t *star;
163 #endif
164 switch (fmt[wcslen(fmt)-1]) {
165 case 'e':
166 case 'E':
167 case 'f':
168 case 'F':
169 case 'g':
170 case 'G':
171 case 'a':
172 case 'A':
173 #ifdef NO_FLOATING_POINT
174 return 0;
175 #else
176 star = wcschr(fmt, '*');
177 if (star) {
178 if (wcschr(star+1, '*')) {
179 int iv1 = va_arg(ap, int);
180 int iv2 = va_arg(ap, int);
181 dv = va_arg(ap, double);
182 n = swprintf(wbuf, 1024, fmt, iv1, iv2, printf_float(dv));
183 } else {
184 int iv = va_arg(ap, int);
185 dv = va_arg(ap, double);
186 n = swprintf(wbuf, 1024, fmt, iv, printf_float(dv));
187 }
188 } else {
189 dv = va_arg(ap, double);
190 n = swprintf(wbuf, 1024, fmt, printf_float(dv));
191 }
192 break;
193 #endif
194 default:
195 n = vswprintf(wbuf, 1024, fmt, ap);
196 break;
197 }
198 va_end(ap);
199 // printf("serial %d expect \"%s\" got \"%s\"\n", serial, expect, wbuf);
200 if (n >= 1024) {
201 failmsgw(serial, L"buffer overflow");
202 free(abuf);
203 return 1;
204 }
205 if (n != (int) wcslen(expect)) {
206 failmsgw(serial, L"expected \"%s\" (%d), got \"%s\" (%d)",
207 expect, wcslen(expect), wbuf, n);
208 free(abuf);
209 return 1;
210 }
211 if (wcscmp(wbuf, expect)) {
212 failmsgw(serial, L"expected \"%ls\", got \"%ls\"", expect, wbuf);
213 free(abuf);
214 return 1;
215 }
216 return 0;
217 }
218
main(void)219 int main(void) {
220 int result = 0;
221 #include "testcases.c"
222 return result;
223 }
224