Annotation of OpenXM_contrib/gmp/tests/misc/t-scanf.c, Revision 1.1.1.1
1.1 ohara 1: /* Test gmp_scanf and related functions.
2:
3: Copyright 2001, 2002 Free Software Foundation, Inc.
4:
5: This file is part of the GNU MP Library.
6:
7: The GNU MP Library is free software; you can redistribute it and/or modify
8: it under the terms of the GNU Lesser General Public License as published by
9: the Free Software Foundation; either version 2.1 of the License, or (at your
10: option) any later version.
11:
12: The GNU MP Library is distributed in the hope that it will be useful, but
13: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14: or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15: License for more details.
16:
17: You should have received a copy of the GNU Lesser General Public License
18: along with the GNU MP Library; see the file COPYING.LIB. If not, write to
19: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20: MA 02111-1307, USA. */
21:
22:
23: /* Usage: t-scanf [-s]
24:
25: -s Check the data against the system scanf, where possible. This is
26: only an option since we don't want to fail if the system scanf is
27: faulty or strange.
28:
29: There's some fairly unattractive repetition between check_z, check_q and
30: check_f, but enough differences to make a common loop or a set of macros
31: seem like too much trouble. */
32:
33:
34: #include "config.h"
35:
36: #if HAVE_STDARG
37: #include <stdarg.h>
38: #else
39: #include <varargs.h>
40: #endif
41:
42: #include <stddef.h> /* for ptrdiff_t */
43: #include <stdio.h>
44: #include <stdlib.h>
45: #include <string.h>
46:
47: #if HAVE_INTTYPES_H
48: # include <inttypes.h> /* for intmax_t */
49: #else
50: # if HAVE_STDINT_H
51: # include <stdint.h>
52: # endif
53: #endif
54:
55: #if HAVE_UNISTD_H
56: #include <unistd.h> /* for unlink */
57: #endif
58:
59: #include "gmp.h"
60: #include "gmp-impl.h"
61: #include "tests.h"
62:
63:
64: #define TEMPFILE "t-scanf.tmp"
65:
66: int option_libc_scanf = 0;
67:
68: typedef int (*fun_t) _PROTO ((const char *, const char *, void *, void *));
69:
70:
71: /* Convert fmt from a GMP scanf format string to an equivalent for a plain
72: libc scanf, for example "%Zd" becomes "%ld". Return 1 if this succeeds,
73: 0 if it cannot (or should not) be done. */
74: int
75: libc_scanf_convert (char *fmt)
76: {
77: char *p = fmt;
78:
79: if (! option_libc_scanf)
80: return 0;
81:
82: for ( ; *fmt != '\0'; fmt++)
83: {
84: switch (*fmt) {
85: case 'F':
86: case 'Q':
87: case 'Z':
88: /* transmute */
89: *p++ = 'l';
90: break;
91: default:
92: *p++ = *fmt;
93: break;
94: }
95: }
96: *p = '\0';
97: return 1;
98: }
99:
100:
101: long got_ftell;
102: int fromstring_next_c;
103:
104: /* Call gmp_fscanf, reading the "input" string data provided. */
105: int
106: #if HAVE_STDARG
107: fromstring_gmp_fscanf (const char *input, const char *fmt, ...)
108: #else
109: fromstring_gmp_fscanf (va_alist)
110: va_dcl
111: #endif
112: {
113: va_list ap;
114: FILE *fp;
115: int ret;
116: #if HAVE_STDARG
117: va_start (ap, fmt);
118: #else
119: const char *input;
120: const char *fmt;
121: va_start (ap);
122: input = va_arg (ap, const char *);
123: fmt = va_arg (ap, const char *);
124: #endif
125:
126: fp = fopen (TEMPFILE, "w+");
127: ASSERT_ALWAYS (fp != NULL);
128: ASSERT_ALWAYS (fputs (input, fp) != EOF);
129: ASSERT_ALWAYS (fflush (fp) == 0);
130: rewind (fp);
131:
132: ret = gmp_vfscanf (fp, fmt, ap);
133: got_ftell = ftell (fp);
134: ASSERT_ALWAYS (got_ftell != -1L);
135:
136: fromstring_next_c = getc (fp);
137:
138: ASSERT_ALWAYS (fclose (fp) == 0);
139: va_end (ap);
140: return ret;
141: }
142:
143:
144: int
145: fun_gmp_sscanf (const char *input, const char *fmt, void *a1, void *a2)
146: {
147: if (a2 == NULL)
148: return gmp_sscanf (input, fmt, a1);
149: else
150: return gmp_sscanf (input, fmt, a1, a2);
151: }
152:
153: int
154: fun_gmp_fscanf (const char *input, const char *fmt, void *a1, void *a2)
155: {
156: if (a2 == NULL)
157: return fromstring_gmp_fscanf (input, fmt, a1);
158: else
159: return fromstring_gmp_fscanf (input, fmt, a1, a2);
160: }
161:
162:
163: int
164: fun_fscanf (const char *input, const char *fmt, void *a1, void *a2)
165: {
166: FILE *fp;
167: int ret;
168:
169: fp = fopen (TEMPFILE, "w+");
170: ASSERT_ALWAYS (fp != NULL);
171: ASSERT_ALWAYS (fputs (input, fp) != EOF);
172: ASSERT_ALWAYS (fflush (fp) == 0);
173: rewind (fp);
174:
175: if (a2 == NULL)
176: ret = fscanf (fp, fmt, a1);
177: else
178: ret = fscanf (fp, fmt, a1, a2);
179:
180: got_ftell = ftell (fp);
181: ASSERT_ALWAYS (got_ftell != -1L);
182:
183: fromstring_next_c = getc (fp);
184:
185: ASSERT_ALWAYS (fclose (fp) == 0);
186: return ret;
187: }
188:
189:
190: /* On various old systems, for instance HP-UX 9, the C library sscanf needs
191: to be able to write into the input string. Ensure that this is possible,
192: when gcc is putting the test data into a read-only section.
193:
194: Actually we ought to only need this under SSCANF_WRITABLE_INPUT from
195: configure, but it's just as easy to do it unconditionally, and in any
196: case this code is only executed under the -s option. */
197:
198: int
199: fun_sscanf (const char *input, const char *fmt, void *a1, void *a2)
200: {
201: char *input_writable;
202: size_t size;
203: int ret;
204:
205: size = strlen (input) + 1;
206: input_writable = (*__gmp_allocate_func) (size);
207: memcpy (input_writable, input, size);
208:
209: if (a2 == NULL)
210: ret = sscanf (input_writable, fmt, a1);
211: else
212: ret = sscanf (input_writable, fmt, a1, a2);
213:
214: (*__gmp_free_func) (input_writable, size);
215: return ret;
216: }
217:
218:
219: /* whether the format string consists entirely of ignored fields */
220: int
221: fmt_allignore (const char *fmt)
222: {
223: int saw_star = 1;
224: for ( ; *fmt != '\0'; fmt++)
225: {
226: switch (*fmt) {
227: case '%':
228: if (! saw_star)
229: return 0;
230: saw_star = 0;
231: break;
232: case '*':
233: saw_star = 1;
234: break;
235: }
236: }
237: return 1;
238: }
239:
240: void
241: check_z (void)
242: {
243: static const struct {
244: const char *fmt;
245: const char *input;
246: const char *want;
247: int want_ret;
248: long want_ftell;
249: int want_upto;
250: int not_glibc;
251:
252: } data[] = {
253:
254: { "%Zd", "0", "0", 1, -1, -1 },
255: { "%Zd", "1", "1", 1, -1, -1 },
256: { "%Zd", "123", "123", 1, -1, -1 },
257: { "%Zd", "+0", "0", 1, -1, -1 },
258: { "%Zd", "+1", "1", 1, -1, -1 },
259: { "%Zd", "+123", "123", 1, -1, -1 },
260: { "%Zd", "-0", "0", 1, -1, -1 },
261: { "%Zd", "-1", "-1", 1, -1, -1 },
262: { "%Zd", "-123", "-123", 1, -1, -1 },
263:
264: { "%Zo", "0", "0", 1, -1, -1 },
265: { "%Zo", "173", "123", 1, -1, -1 },
266: { "%Zo", "+0", "0", 1, -1, -1 },
267: { "%Zo", "+173", "123", 1, -1, -1 },
268: { "%Zo", "-0", "0", 1, -1, -1 },
269: { "%Zo", "-173", "-123", 1, -1, -1 },
270:
271: { "%Zx", "0", "0", 1, -1, -1 },
272: { "%Zx", "7b", "123", 1, -1, -1 },
273: { "%Zx", "7b", "123", 1, -1, -1 },
274: { "%Zx", "+0", "0", 1, -1, -1 },
275: { "%Zx", "+7b", "123", 1, -1, -1 },
276: { "%Zx", "+7b", "123", 1, -1, -1 },
277: { "%Zx", "-0", "-0", 1, -1, -1 },
278: { "%Zx", "-7b", "-123", 1, -1, -1 },
279: { "%Zx", "-7b", "-123", 1, -1, -1 },
280: { "%ZX", "0", "0", 1, -1, -1 },
281: { "%ZX", "7b", "123", 1, -1, -1 },
282: { "%ZX", "7b", "123", 1, -1, -1 },
283: { "%ZX", "+0", "0", 1, -1, -1 },
284: { "%ZX", "+7b", "123", 1, -1, -1 },
285: { "%ZX", "+7b", "123", 1, -1, -1 },
286: { "%ZX", "-0", "-0", 1, -1, -1 },
287: { "%ZX", "-7b", "-123", 1, -1, -1 },
288: { "%ZX", "-7b", "-123", 1, -1, -1 },
289: { "%Zx", "0", "0", 1, -1, -1 },
290: { "%Zx", "7B", "123", 1, -1, -1 },
291: { "%Zx", "7B", "123", 1, -1, -1 },
292: { "%Zx", "+0", "0", 1, -1, -1 },
293: { "%Zx", "+7B", "123", 1, -1, -1 },
294: { "%Zx", "+7B", "123", 1, -1, -1 },
295: { "%Zx", "-0", "-0", 1, -1, -1 },
296: { "%Zx", "-7B", "-123", 1, -1, -1 },
297: { "%Zx", "-7B", "-123", 1, -1, -1 },
298: { "%ZX", "0", "0", 1, -1, -1 },
299: { "%ZX", "7B", "123", 1, -1, -1 },
300: { "%ZX", "7B", "123", 1, -1, -1 },
301: { "%ZX", "+0", "0", 1, -1, -1 },
302: { "%ZX", "+7B", "123", 1, -1, -1 },
303: { "%ZX", "+7B", "123", 1, -1, -1 },
304: { "%ZX", "-0", "-0", 1, -1, -1 },
305: { "%ZX", "-7B", "-123", 1, -1, -1 },
306: { "%ZX", "-7B", "-123", 1, -1, -1 },
307:
308: { "%Zi", "0", "0", 1, -1, -1 },
309: { "%Zi", "1", "1", 1, -1, -1 },
310: { "%Zi", "123", "123", 1, -1, -1 },
311: { "%Zi", "+0", "0", 1, -1, -1 },
312: { "%Zi", "+1", "1", 1, -1, -1 },
313: { "%Zi", "+123", "123", 1, -1, -1 },
314: { "%Zi", "-0", "0", 1, -1, -1 },
315: { "%Zi", "-1", "-1", 1, -1, -1 },
316: { "%Zi", "-123", "-123", 1, -1, -1 },
317:
318: { "%Zi", "00", "0", 1, -1, -1 },
319: { "%Zi", "0173", "123", 1, -1, -1 },
320: { "%Zi", "+00", "0", 1, -1, -1 },
321: { "%Zi", "+0173", "123", 1, -1, -1 },
322: { "%Zi", "-00", "0", 1, -1, -1 },
323: { "%Zi", "-0173", "-123", 1, -1, -1 },
324:
325: { "%Zi", "0x0", "0", 1, -1, -1 },
326: { "%Zi", "0x7b", "123", 1, -1, -1 },
327: { "%Zi", "0x7b", "123", 1, -1, -1 },
328: { "%Zi", "+0x0", "0", 1, -1, -1 },
329: { "%Zi", "+0x7b", "123", 1, -1, -1 },
330: { "%Zi", "+0x7b", "123", 1, -1, -1 },
331: { "%Zi", "-0x0", "-0", 1, -1, -1 },
332: { "%Zi", "-0x7b", "-123", 1, -1, -1 },
333: { "%Zi", "-0x7b", "-123", 1, -1, -1 },
334: { "%Zi", "0X0", "0", 1, -1, -1 },
335: { "%Zi", "0X7b", "123", 1, -1, -1 },
336: { "%Zi", "0X7b", "123", 1, -1, -1 },
337: { "%Zi", "+0X0", "0", 1, -1, -1 },
338: { "%Zi", "+0X7b", "123", 1, -1, -1 },
339: { "%Zi", "+0X7b", "123", 1, -1, -1 },
340: { "%Zi", "-0X0", "-0", 1, -1, -1 },
341: { "%Zi", "-0X7b", "-123", 1, -1, -1 },
342: { "%Zi", "-0X7b", "-123", 1, -1, -1 },
343: { "%Zi", "0x0", "0", 1, -1, -1 },
344: { "%Zi", "0x7B", "123", 1, -1, -1 },
345: { "%Zi", "0x7B", "123", 1, -1, -1 },
346: { "%Zi", "+0x0", "0", 1, -1, -1 },
347: { "%Zi", "+0x7B", "123", 1, -1, -1 },
348: { "%Zi", "+0x7B", "123", 1, -1, -1 },
349: { "%Zi", "-0x0", "-0", 1, -1, -1 },
350: { "%Zi", "-0x7B", "-123", 1, -1, -1 },
351: { "%Zi", "-0x7B", "-123", 1, -1, -1 },
352: { "%Zi", "0X0", "0", 1, -1, -1 },
353: { "%Zi", "0X7B", "123", 1, -1, -1 },
354: { "%Zi", "0X7B", "123", 1, -1, -1 },
355: { "%Zi", "+0X0", "0", 1, -1, -1 },
356: { "%Zi", "+0X7B", "123", 1, -1, -1 },
357: { "%Zi", "+0X7B", "123", 1, -1, -1 },
358: { "%Zi", "-0X0", "-0", 1, -1, -1 },
359: { "%Zi", "-0X7B", "-123", 1, -1, -1 },
360: { "%Zi", "-0X7B", "-123", 1, -1, -1 },
361:
362: { "%Zd", " 0", "0", 1, -1, -1 },
363: { "%Zd", " 0", "0", 1, -1, -1 },
364: { "%Zd", " 0", "0", 1, -1, -1 },
365: { "%Zd", "\t0", "0", 1, -1, -1 },
366: { "%Zd", "\t\t0", "0", 1, -1, -1 },
367:
368: { "hello%Zd", "hello0", "0", 1, -1, -1 },
369: { "hello%Zd", "hello 0", "0", 1, -1, -1 },
370: { "hello%Zd", "hello \t0", "0", 1, -1, -1 },
371: { "hello%Zdworld", "hello 0world", "0", 1, -1, -1 },
372:
373: { "hello%*Zd", "hello0", "-999", 0, -1, -1 },
374: { "hello%*Zd", "hello 0", "-999", 0, -1, -1 },
375: { "hello%*Zd", "hello \t0", "-999", 0, -1, -1 },
376: { "hello%*Zdworld", "hello 0world", "-999", 0, -1, -1 },
377:
378: { "%Zd", "", "-999", -1, -1, -555 },
379: { "%Zd", " ", "-999", -1, -1, -555 },
380: { " %Zd", "", "-999", -1, -1, -555 },
381: { "xyz%Zd", "", "-999", -1, -1, -555 },
382:
383: { "%*Zd", "", "-999", -1, -1, -555 },
384: { " %*Zd", "", "-999", -1, -1, -555 },
385: { "xyz%*Zd", "", "-999", -1, -1, -555 },
386:
387: { "%Zd", "xyz", "0", 0, 0, -555 },
388:
389: /* match something, but invalid */
390: { "%Zd", "-", "-999", 0, 1, -555 },
391: { "%Zd", "+", "-999", 0, 1, -555 },
392: { "xyz%Zd", "xyz-", "-999", 0, 4, -555 },
393: { "xyz%Zd", "xyz+", "-999", 0, 4, -555 },
394:
395: { "%1Zi", "1234", "1", 1, 1, 1 },
396: { "%2Zi", "1234", "12", 1, 2, 2 },
397: { "%3Zi", "1234", "123", 1, 3, 3 },
398: { "%4Zi", "1234", "1234", 1, 4, 4 },
399: { "%5Zi", "1234", "1234", 1, 4, 4 },
400: { "%6Zi", "1234", "1234", 1, 4, 4 },
401:
402: { "%1Zi", "01234", "0", 1, 1, 1 },
403: { "%2Zi", "01234", "01", 1, 2, 2 },
404: { "%3Zi", "01234", "012", 1, 3, 3 },
405: { "%4Zi", "01234", "0123", 1, 4, 4 },
406: { "%5Zi", "01234", "01234", 1, 5, 5 },
407: { "%6Zi", "01234", "01234", 1, 5, 5 },
408: { "%7Zi", "01234", "01234", 1, 5, 5 },
409:
410: { "%1Zi", "0x1234", "0", 1, 1, 1 },
411: { "%2Zi", "0x1234", "0", 1, 2, 2 },
412: { "%3Zi", "0x1234", "0x1", 1, 3, 3 },
413: { "%4Zi", "0x1234", "0x12", 1, 4, 4 },
414: { "%5Zi", "0x1234", "0x123", 1, 5, 5 },
415: { "%6Zi", "0x1234", "0x1234", 1, 6, 6 },
416: { "%7Zi", "0x1234", "0x1234", 1, 6, 6 },
417: { "%8Zi", "0x1234", "0x1234", 1, 6, 6 },
418:
419: { "%%xyz%Zd", "%xyz123", "123", 1, -1, -1 },
420: { "12%%34%Zd", "12%34567", "567", 1, -1, -1 },
421: { "%%%%%Zd", "%%123", "123", 1, -1, -1 },
422:
423: /* various subtle EOF cases */
424: { "x", "", "-999", EOF, 0, -555 },
425: { " x", "", "-999", EOF, 0, -555 },
426: { "xyz", "", "-999", EOF, 0, -555 },
427: { " ", "", "-999", 0, 0, 0 },
428: { " ", " ", "-999", 0, 1, 1 },
429: { "%*Zd%Zd", "", "-999", EOF, 0, -555 },
430: { "%*Zd%Zd", "123", "-999", EOF, 3, -555 },
431: { "x", "x", "-999", 0, 1, 1 },
432: { "xyz", "x", "-999", EOF, 1, -555 },
433: { "xyz", "xy", "-999", EOF, 2, -555 },
434: { "xyz", "xyz", "-999", 0, 3, 3 },
435: { "%Zn", "", "0", 0, 0, 0 },
436: { " %Zn", "", "0", 0, 0, 0 },
437: { " x%Zn", "", "-999", EOF, 0, -555 },
438: { "xyz%Zn", "", "-999", EOF, 0, -555 },
439: { " x%Zn", "", "-999", EOF, 0, -555 },
440: { " %Zn x", " ", "-999", EOF, 1, -555 },
441:
442: /* these seem to tickle a bug in glibc 2.2.4 */
443: { " x", " ", "-999", EOF, 1, -555, 1 },
444: { " xyz", " ", "-999", EOF, 1, -555, 1 },
445: { " x%Zn", " ", "-999", EOF, 1, -555, 1 },
446: };
447:
448: int i, j, ignore;
449: int got_ret, want_ret, got_upto, want_upto;
450: mpz_t got, want;
451: long got_l, want_ftell;
452: int error = 0;
453: fun_t fun;
454: const char *name;
455: char fmt[128];
456:
457: mpz_init (got);
458: mpz_init (want);
459:
460: for (i = 0; i < numberof (data); i++)
461: {
462: mpz_set_str_or_abort (want, data[i].want, 0);
463:
464: ASSERT_ALWAYS (strlen (data[i].fmt) + 2 < sizeof (fmt));
465: strcpy (fmt, data[i].fmt);
466: strcat (fmt, "%n");
467:
468: ignore = fmt_allignore (fmt);
469:
470: for (j = 0; j <= 3; j++)
471: {
472: want_ret = data[i].want_ret;
473:
474: want_ftell = data[i].want_ftell;
475: if (want_ftell == -1)
476: want_ftell = strlen (data[i].input);
477:
478: want_upto = data[i].want_upto;
479: if (want_upto == -1)
480: want_upto = strlen (data[i].input);
481:
482: switch (j) {
483: case 0:
484: name = "gmp_sscanf";
485: fun = fun_gmp_sscanf;
486: break;
487: case 1:
488: name = "gmp_fscanf";
489: fun = fun_gmp_fscanf;
490: break;
491: case 2:
492: #ifdef __GLIBC__
493: if (data[i].not_glibc)
494: continue;
495: #endif
496: if (! libc_scanf_convert (fmt))
497: continue;
498: name = "standard sscanf";
499: fun = fun_sscanf;
500: break;
501: case 3:
502: #ifdef __GLIBC__
503: if (data[i].not_glibc)
504: continue;
505: #endif
506: if (! libc_scanf_convert (fmt))
507: continue;
508: name = "standard fscanf";
509: fun = fun_fscanf;
510: break;
511: default:
512: ASSERT_ALWAYS (0);
513: break;
514: }
515:
516: got_upto = -555;
517: got_ftell = -1L;
518:
519: switch (j) {
520: case 0:
521: case 1:
522: mpz_set_si (got, -999L);
523: if (ignore)
524: got_ret = (*fun) (data[i].input, fmt, &got_upto, NULL);
525: else
526: got_ret = (*fun) (data[i].input, fmt, got, &got_upto);
527: break;
528: case 2:
529: case 3:
530: got_l = -999L;
531: if (ignore)
532: got_ret = (*fun) (data[i].input, fmt, &got_upto, NULL);
533: else
534: got_ret = (*fun) (data[i].input, fmt, &got_l, &got_upto);
535: mpz_set_si (got, got_l);
536: break;
537: default:
538: ASSERT_ALWAYS (0);
539: break;
540: }
541:
542: MPZ_CHECK_FORMAT (got);
543:
544: if (got_ret != want_ret)
545: {
546: printf ("%s wrong return value\n", name);
547: error = 1;
548: }
549: if (want_ret == 1 && mpz_cmp (want, got) != 0)
550: {
551: printf ("%s wrong result\n", name);
552: error = 1;
553: }
554: if (got_upto != want_upto)
555: {
556: printf ("%s wrong upto\n", name);
557: error = 1;
558: }
559: if (got_ftell != -1 && want_ftell != -1 && got_ftell != want_ftell)
560: {
561: printf ("%s wrong ftell\n", name);
562: error = 1;
563: }
564: if (error)
565: {
566: printf (" fmt \"%s\"\n", data[i].fmt);
567: printf (" input \"%s\"\n", data[i].input);
568: printf (" ignore %d\n", ignore);
569: printf (" ret want=%d\n", want_ret);
570: printf (" got =%d\n", got_ret);
571: mpz_trace (" value want", want);
572: mpz_trace (" got ", got);
573: printf (" upto want =%d\n", want_upto);
574: printf (" got =%d\n", got_upto);
575: if (got_ftell != -1)
576: {
577: printf (" ftell want =%ld\n", want_ftell);
578: printf (" got =%ld\n", got_ftell);
579: }
580: abort ();
581: }
582: }
583: }
584:
585: mpz_clear (got);
586: mpz_clear (want);
587: }
588:
589: void
590: check_q (void)
591: {
592: static const struct {
593: const char *fmt;
594: const char *input;
595: const char *want;
596: int ret;
597: long ftell;
598:
599: } data[] = {
600:
601: { "%Qd", "0", "0", 1, -1 },
602: { "%Qd", "1", "1", 1, -1 },
603: { "%Qd", "123", "123", 1, -1 },
604: { "%Qd", "+0", "0", 1, -1 },
605: { "%Qd", "+1", "1", 1, -1 },
606: { "%Qd", "+123", "123", 1, -1 },
607: { "%Qd", "-0", "0", 1, -1 },
608: { "%Qd", "-1", "-1", 1, -1 },
609: { "%Qd", "-123", "-123", 1, -1 },
610:
611: { "%Qo", "0", "0", 1, -1 },
612: { "%Qo", "173", "123", 1, -1 },
613: { "%Qo", "+0", "0", 1, -1 },
614: { "%Qo", "+173", "123", 1, -1 },
615: { "%Qo", "-0", "0", 1, -1 },
616: { "%Qo", "-173", "-123", 1, -1 },
617:
618: { "%Qx", "0", "0", 1, -1 },
619: { "%Qx", "7b", "123", 1, -1 },
620: { "%Qx", "7b", "123", 1, -1 },
621: { "%Qx", "+0", "0", 1, -1 },
622: { "%Qx", "+7b", "123", 1, -1 },
623: { "%Qx", "+7b", "123", 1, -1 },
624: { "%Qx", "-0", "-0", 1, -1 },
625: { "%Qx", "-7b", "-123", 1, -1 },
626: { "%Qx", "-7b", "-123", 1, -1 },
627: { "%QX", "0", "0", 1, -1 },
628: { "%QX", "7b", "123", 1, -1 },
629: { "%QX", "7b", "123", 1, -1 },
630: { "%QX", "+0", "0", 1, -1 },
631: { "%QX", "+7b", "123", 1, -1 },
632: { "%QX", "+7b", "123", 1, -1 },
633: { "%QX", "-0", "-0", 1, -1 },
634: { "%QX", "-7b", "-123", 1, -1 },
635: { "%QX", "-7b", "-123", 1, -1 },
636: { "%Qx", "0", "0", 1, -1 },
637: { "%Qx", "7B", "123", 1, -1 },
638: { "%Qx", "7B", "123", 1, -1 },
639: { "%Qx", "+0", "0", 1, -1 },
640: { "%Qx", "+7B", "123", 1, -1 },
641: { "%Qx", "+7B", "123", 1, -1 },
642: { "%Qx", "-0", "-0", 1, -1 },
643: { "%Qx", "-7B", "-123", 1, -1 },
644: { "%Qx", "-7B", "-123", 1, -1 },
645: { "%QX", "0", "0", 1, -1 },
646: { "%QX", "7B", "123", 1, -1 },
647: { "%QX", "7B", "123", 1, -1 },
648: { "%QX", "+0", "0", 1, -1 },
649: { "%QX", "+7B", "123", 1, -1 },
650: { "%QX", "+7B", "123", 1, -1 },
651: { "%QX", "-0", "-0", 1, -1 },
652: { "%QX", "-7B", "-123", 1, -1 },
653: { "%QX", "-7B", "-123", 1, -1 },
654:
655: { "%Qi", "0", "0", 1, -1 },
656: { "%Qi", "1", "1", 1, -1 },
657: { "%Qi", "123", "123", 1, -1 },
658: { "%Qi", "+0", "0", 1, -1 },
659: { "%Qi", "+1", "1", 1, -1 },
660: { "%Qi", "+123", "123", 1, -1 },
661: { "%Qi", "-0", "0", 1, -1 },
662: { "%Qi", "-1", "-1", 1, -1 },
663: { "%Qi", "-123", "-123", 1, -1 },
664:
665: { "%Qi", "00", "0", 1, -1 },
666: { "%Qi", "0173", "123", 1, -1 },
667: { "%Qi", "+00", "0", 1, -1 },
668: { "%Qi", "+0173", "123", 1, -1 },
669: { "%Qi", "-00", "0", 1, -1 },
670: { "%Qi", "-0173", "-123", 1, -1 },
671:
672: { "%Qi", "0x0", "0", 1, -1 },
673: { "%Qi", "0x7b", "123", 1, -1 },
674: { "%Qi", "0x7b", "123", 1, -1 },
675: { "%Qi", "+0x0", "0", 1, -1 },
676: { "%Qi", "+0x7b", "123", 1, -1 },
677: { "%Qi", "+0x7b", "123", 1, -1 },
678: { "%Qi", "-0x0", "-0", 1, -1 },
679: { "%Qi", "-0x7b", "-123", 1, -1 },
680: { "%Qi", "-0x7b", "-123", 1, -1 },
681: { "%Qi", "0X0", "0", 1, -1 },
682: { "%Qi", "0X7b", "123", 1, -1 },
683: { "%Qi", "0X7b", "123", 1, -1 },
684: { "%Qi", "+0X0", "0", 1, -1 },
685: { "%Qi", "+0X7b", "123", 1, -1 },
686: { "%Qi", "+0X7b", "123", 1, -1 },
687: { "%Qi", "-0X0", "-0", 1, -1 },
688: { "%Qi", "-0X7b", "-123", 1, -1 },
689: { "%Qi", "-0X7b", "-123", 1, -1 },
690: { "%Qi", "0x0", "0", 1, -1 },
691: { "%Qi", "0x7B", "123", 1, -1 },
692: { "%Qi", "0x7B", "123", 1, -1 },
693: { "%Qi", "+0x0", "0", 1, -1 },
694: { "%Qi", "+0x7B", "123", 1, -1 },
695: { "%Qi", "+0x7B", "123", 1, -1 },
696: { "%Qi", "-0x0", "-0", 1, -1 },
697: { "%Qi", "-0x7B", "-123", 1, -1 },
698: { "%Qi", "-0x7B", "-123", 1, -1 },
699: { "%Qi", "0X0", "0", 1, -1 },
700: { "%Qi", "0X7B", "123", 1, -1 },
701: { "%Qi", "0X7B", "123", 1, -1 },
702: { "%Qi", "+0X0", "0", 1, -1 },
703: { "%Qi", "+0X7B", "123", 1, -1 },
704: { "%Qi", "+0X7B", "123", 1, -1 },
705: { "%Qi", "-0X0", "-0", 1, -1 },
706: { "%Qi", "-0X7B", "-123", 1, -1 },
707: { "%Qi", "-0X7B", "-123", 1, -1 },
708:
709: { "%Qd", " 0", "0", 1, -1 },
710: { "%Qd", " 0", "0", 1, -1 },
711: { "%Qd", " 0", "0", 1, -1 },
712: { "%Qd", "\t0", "0", 1, -1 },
713: { "%Qd", "\t\t0", "0", 1, -1 },
714:
715: { "%Qd", "3/2", "3/2", 1, -1 },
716: { "%Qd", "+3/2", "3/2", 1, -1 },
717: { "%Qd", "-3/2", "-3/2", 1, -1 },
718:
719: { "%Qx", "f/10", "15/16", 1, -1 },
720: { "%Qx", "F/10", "15/16", 1, -1 },
721: { "%QX", "f/10", "15/16", 1, -1 },
722: { "%QX", "F/10", "15/16", 1, -1 },
723:
724: { "%Qo", "20/21", "16/17", 1, -1 },
725: { "%Qo", "-20/21", "-16/17", 1, -1 },
726:
727: { "%Qi", "10/11", "10/11", 1, -1 },
728: { "%Qi", "+10/11", "10/11", 1, -1 },
729: { "%Qi", "-10/11", "-10/11", 1, -1 },
730: { "%Qi", "010/11", "8/11", 1, -1 },
731: { "%Qi", "+010/11", "8/11", 1, -1 },
732: { "%Qi", "-010/11", "-8/11", 1, -1 },
733: { "%Qi", "0x10/11", "16/11", 1, -1 },
734: { "%Qi", "+0x10/11", "16/11", 1, -1 },
735: { "%Qi", "-0x10/11", "-16/11", 1, -1 },
736:
737: { "%Qi", "10/011", "10/9", 1, -1 },
738: { "%Qi", "+10/011", "10/9", 1, -1 },
739: { "%Qi", "-10/011", "-10/9", 1, -1 },
740: { "%Qi", "010/011", "8/9", 1, -1 },
741: { "%Qi", "+010/011", "8/9", 1, -1 },
742: { "%Qi", "-010/011", "-8/9", 1, -1 },
743: { "%Qi", "0x10/011", "16/9", 1, -1 },
744: { "%Qi", "+0x10/011", "16/9", 1, -1 },
745: { "%Qi", "-0x10/011", "-16/9", 1, -1 },
746:
747: { "%Qi", "10/0x11", "10/17", 1, -1 },
748: { "%Qi", "+10/0x11", "10/17", 1, -1 },
749: { "%Qi", "-10/0x11", "-10/17", 1, -1 },
750: { "%Qi", "010/0x11", "8/17", 1, -1 },
751: { "%Qi", "+010/0x11", "8/17", 1, -1 },
752: { "%Qi", "-010/0x11", "-8/17", 1, -1 },
753: { "%Qi", "0x10/0x11", "16/17", 1, -1 },
754: { "%Qi", "+0x10/0x11", "16/17", 1, -1 },
755: { "%Qi", "-0x10/0x11", "-16/17", 1, -1 },
756:
757: { "hello%Qd", "hello0", "0", 1, -1 },
758: { "hello%Qd", "hello 0", "0", 1, -1 },
759: { "hello%Qd", "hello \t0", "0", 1, -1 },
760: { "hello%Qdworld", "hello 0world", "0", 1, -1 },
761: { "hello%Qd", "hello3/2", "3/2", 1, -1 },
762:
763: { "hello%*Qd", "hello0", "-999/121", 0, -1 },
764: { "hello%*Qd", "hello 0", "-999/121", 0, -1 },
765: { "hello%*Qd", "hello \t0", "-999/121", 0, -1 },
766: { "hello%*Qdworld", "hello 0world", "-999/121", 0, -1 },
767: { "hello%*Qdworld", "hello3/2world", "-999/121", 0, -1 },
768:
769: { "%Qd", "", "-999/121", -1, -1 },
770: { "%Qd", " ", "-999/121", -1, -1 },
771: { " %Qd", "", "-999/121", -1, -1 },
772: { "xyz%Qd", "", "-999/121", -1, -1 },
773:
774: { "%*Qd", "", "-999/121", -1, -1 },
775: { " %*Qd", "", "-999/121", -1, -1 },
776: { "xyz%*Qd", "", "-999/121", -1, -1 },
777:
778: /* match something, but invalid */
779: { "%Qd", "-", "-999/121", 0, 1 },
780: { "%Qd", "+", "-999/121", 0, 1 },
781: { "%Qd", "/-", "-999/121", 0, 1 },
782: { "%Qd", "/+", "-999/121", 0, 1 },
783: { "%Qd", "-/", "-999/121", 0, 1 },
784: { "%Qd", "+/", "-999/121", 0, 1 },
785: { "%Qd", "-/-", "-999/121", 0, 1 },
786: { "%Qd", "-/+", "-999/121", 0, 1 },
787: { "%Qd", "+/+", "-999/121", 0, 1 },
788: { "%Qd", "/123", "-999/121", 0, 1 },
789: { "%Qd", "-/123", "-999/121", 0, 1 },
790: { "%Qd", "+/123", "-999/121", 0, 1 },
791: { "%Qd", "123/", "-999/121", 0, 1 },
792: { "%Qd", "123/-", "-999/121", 0, 1 },
793: { "%Qd", "123/+", "-999/121", 0, 1 },
794: { "xyz%Qd", "xyz-", "-999/121", 0, 4 },
795: { "xyz%Qd", "xyz+", "-999/121", 0, 4 },
796:
797: { "%1Qi", "12/57", "1", 1, 1 },
798: { "%2Qi", "12/57", "12", 1, 2 },
799: { "%3Qi", "12/57", "-999/121", 0, -1 },
800: { "%4Qi", "12/57", "12/5", 1, 4 },
801: { "%5Qi", "12/57", "12/57", 1, 5 },
802: { "%6Qi", "12/57", "12/57", 1, 5 },
803: { "%7Qi", "12/57", "12/57", 1, 5 },
804:
805: { "%1Qi", "012/057", "0", 1, 1 },
806: { "%2Qi", "012/057", "01", 1, 2 },
807: { "%3Qi", "012/057", "012", 1, 3 },
808: { "%4Qi", "012/057", "-999/121", 0, -1 },
809: { "%5Qi", "012/057", "012/0", 1, 5 },
810: { "%6Qi", "012/057", "012/5", 1, 6 },
811: { "%7Qi", "012/057", "012/057", 1, 7 },
812: { "%8Qi", "012/057", "012/057", 1, 7 },
813: { "%9Qi", "012/057", "012/057", 1, 7 },
814:
815: { "%1Qi", "0x12/0x57", "0", 1, 1 },
816: { "%2Qi", "0x12/0x57", "0", 1, 2 },
817: { "%3Qi", "0x12/0x57", "0x1", 1, 3 },
818: { "%4Qi", "0x12/0x57", "0x12", 1, 4 },
819: { "%5Qi", "0x12/0x57", "-999/121", 0, -1 },
820: { "%6Qi", "0x12/0x57", "0x12/0", 1, 6 },
821: { "%7Qi", "0x12/0x57", "0x12/0", 1, 7 },
822: { "%8Qi", "0x12/0x57", "0x12/0x5", 1, 8 },
823: { "%9Qi", "0x12/0x57", "0x12/0x57", 1, 9 },
824: { "%10Qi", "0x12/0x57", "0x12/0x57", 1, 9 },
825: { "%11Qi", "0x12/0x57", "0x12/0x57", 1, 9 },
826:
827: { "%Qd", "xyz", "0", 0, 0 },
828: };
829:
830: int i, j, ignore, got_ret, want_ret, got_upto, want_upto;
831: mpq_t got, want;
832: long got_l, want_ftell;
833: int error = 0;
834: fun_t fun;
835: const char *name;
836: char fmt[128];
837:
838: mpq_init (got);
839: mpq_init (want);
840:
841: for (i = 0; i < numberof (data); i++)
842: {
843: mpq_set_str_or_abort (want, data[i].want, 0);
844:
845: ASSERT_ALWAYS (strlen (data[i].fmt) + 2 < sizeof (fmt));
846: strcpy (fmt, data[i].fmt);
847: strcat (fmt, "%n");
848:
849: ignore = (strchr (fmt, '*') != NULL);
850:
851: for (j = 0; j <= 3; j++)
852: {
853: want_ret = data[i].ret;
854:
855: want_ftell = data[i].ftell;
856: if (want_ftell == -1)
857: want_ftell = strlen (data[i].input);
858: want_upto = want_ftell;
859:
860: if (want_ret == -1 || (want_ret == 0 && ! ignore))
861: {
862: want_ftell = -1;
863: want_upto = -555;
864: }
865:
866: switch (j) {
867: case 0:
868: name = "gmp_sscanf";
869: fun = fun_gmp_sscanf;
870: break;
871: case 1:
872: name = "gmp_fscanf";
873: fun = fun_gmp_fscanf;
874: break;
875: case 2:
876: if (strchr (data[i].input, '/') != NULL)
877: continue;
878: if (! libc_scanf_convert (fmt))
879: continue;
880: name = "standard sscanf";
881: fun = fun_sscanf;
882: break;
883: case 3:
884: if (strchr (data[i].input, '/') != NULL)
885: continue;
886: if (! libc_scanf_convert (fmt))
887: continue;
888: name = "standard fscanf";
889: fun = fun_fscanf;
890: break;
891: default:
892: ASSERT_ALWAYS (0);
893: break;
894: }
895:
896: got_upto = -555;
897: got_ftell = -1;
898:
899: switch (j) {
900: case 0:
901: case 1:
902: mpq_set_si (got, -999L, 121L);
903: if (ignore)
904: got_ret = (*fun) (data[i].input, fmt, &got_upto, NULL);
905: else
906: got_ret = (*fun) (data[i].input, fmt, got, &got_upto);
907: break;
908: case 2:
909: case 3:
910: got_l = -999L;
911: if (ignore)
912: got_ret = (*fun) (data[i].input, fmt, &got_upto, NULL);
913: else
914: got_ret = (*fun) (data[i].input, fmt, &got_l, &got_upto);
915: mpq_set_si (got, got_l, (got_l == -999L ? 121L : 1L));
916: break;
917: default:
918: ASSERT_ALWAYS (0);
919: break;
920: }
921:
922: MPZ_CHECK_FORMAT (mpq_numref (got));
923: MPZ_CHECK_FORMAT (mpq_denref (got));
924:
925: if (got_ret != want_ret)
926: {
927: printf ("%s wrong return value\n", name);
928: error = 1;
929: }
930: /* use direct mpz compares, since some of the test data is
931: non-canonical and can trip ASSERTs in mpq_equal */
932: if (want_ret == 1
933: && ! (mpz_cmp (mpq_numref(want), mpq_numref(got)) == 0
934: && mpz_cmp (mpq_denref(want), mpq_denref(got)) == 0))
935: {
936: printf ("%s wrong result\n", name);
937: error = 1;
938: }
939: if (got_upto != want_upto)
940: {
941: printf ("%s wrong upto\n", name);
942: error = 1;
943: }
944: if (got_ftell != -1 && want_ftell != -1 && got_ftell != want_ftell)
945: {
946: printf ("%s wrong ftell\n", name);
947: error = 1;
948: }
949: if (error)
950: {
951: printf (" fmt \"%s\"\n", data[i].fmt);
952: printf (" input \"%s\"\n", data[i].input);
953: printf (" ret want=%d\n", want_ret);
954: printf (" got =%d\n", got_ret);
955: mpq_trace (" value want", want);
956: mpq_trace (" got ", got);
957: printf (" upto want=%d\n", want_upto);
958: printf (" got =%d\n", got_upto);
959: if (got_ftell != -1)
960: {
961: printf (" ftell want =%ld\n", want_ftell);
962: printf (" got =%ld\n", got_ftell);
963: }
964: abort ();
965: }
966: }
967: }
968:
969: mpq_clear (got);
970: mpq_clear (want);
971: }
972:
973: void
974: check_f (void)
975: {
976: static const struct {
977: const char *fmt;
978: const char *input;
979: const char *want;
980: int ret;
981: long ftell;
982:
983: } data[] = {
984:
985: { "%Ff", "0", "0", 1, -1 },
986: { "%Fe", "0", "0", 1, -1 },
987: { "%FE", "0", "0", 1, -1 },
988: { "%Fg", "0", "0", 1, -1 },
989: { "%FG", "0", "0", 1, -1 },
990:
991: { "%Ff", "123", "123", 1, -1 },
992: { "%Ff", "+123", "123", 1, -1 },
993: { "%Ff", "-123", "-123", 1, -1 },
994: { "%Ff", "123.", "123", 1, -1 },
995: { "%Ff", "+123.", "123", 1, -1 },
996: { "%Ff", "-123.", "-123", 1, -1 },
997: { "%Ff", "123.0", "123", 1, -1 },
998: { "%Ff", "+123.0", "123", 1, -1 },
999: { "%Ff", "-123.0", "-123", 1, -1 },
1000: { "%Ff", "123e", "123", 1, -1 },
1001: { "%Ff", "-123e", "-123", 1, -1 },
1002: { "%Ff", "123e-", "123", 1, -1 },
1003: { "%Ff", "-123e-", "-123", 1, -1 },
1004: { "%Ff", "123e+", "123", 1, -1 },
1005: { "%Ff", "-123e+", "-123", 1, -1 },
1006:
1007: { "%Ff", "123.456e3", "123456", 1, -1 },
1008: { "%Ff", "-123.456e3", "-123456", 1, -1 },
1009: { "%Ff", "123.456e+3", "123456", 1, -1 },
1010: { "%Ff", "-123.456e+3", "-123456", 1, -1 },
1011: { "%Ff", "123000e-3", "123", 1, -1 },
1012: { "%Ff", "-123000e-3", "-123", 1, -1 },
1013: { "%Ff", "123000.e-3", "123", 1, -1 },
1014: { "%Ff", "-123000.e-3", "-123", 1, -1 },
1015:
1016: { "%Ff", "123.456E3", "123456", 1, -1 },
1017: { "%Ff", "-123.456E3", "-123456", 1, -1 },
1018: { "%Ff", "123.456E+3", "123456", 1, -1 },
1019: { "%Ff", "-123.456E+3", "-123456", 1, -1 },
1020: { "%Ff", "123000E-3", "123", 1, -1 },
1021: { "%Ff", "-123000E-3", "-123", 1, -1 },
1022: { "%Ff", "123000.E-3", "123", 1, -1 },
1023: { "%Ff", "-123000.E-3", "-123", 1, -1 },
1024:
1025: { "%Ff", ".456e3", "456", 1, -1 },
1026: { "%Ff", "-.456e3", "-456", 1, -1 },
1027: { "%Ff", ".456e+3", "456", 1, -1 },
1028: { "%Ff", "-.456e+3", "-456", 1, -1 },
1029:
1030: { "%Ff", " 0", "0", 1, -1 },
1031: { "%Ff", " 0", "0", 1, -1 },
1032: { "%Ff", " 0", "0", 1, -1 },
1033: { "%Ff", "\t0", "0", 1, -1 },
1034: { "%Ff", "\t\t0", "0", 1, -1 },
1035:
1036: { "hello%Fg", "hello0", "0", 1, -1 },
1037: { "hello%Fg", "hello 0", "0", 1, -1 },
1038: { "hello%Fg", "hello \t0", "0", 1, -1 },
1039: { "hello%Fgworld", "hello 0world", "0", 1, -1 },
1040: { "hello%Fg", "hello3.0", "3.0", 1, -1 },
1041:
1042: { "hello%*Fg", "hello0", "-999", 0, -1 },
1043: { "hello%*Fg", "hello 0", "-999", 0, -1 },
1044: { "hello%*Fg", "hello \t0", "-999", 0, -1 },
1045: { "hello%*Fgworld", "hello 0world", "-999", 0, -1 },
1046: { "hello%*Fgworld", "hello3.0world", "-999", 0, -1 },
1047:
1048: { "%Ff", "", "-999", -1, -1 },
1049: { "%Ff", " ", "-999", -1, -1 },
1050: { "%Ff", "\t", "-999", -1, -1 },
1051: { "%Ff", " \t", "-999", -1, -1 },
1052: { " %Ff", "", "-999", -1, -1 },
1053: { "xyz%Ff", "", "-999", -1, -1 },
1054:
1055: { "%*Ff", "", "-999", -1, -1 },
1056: { " %*Ff", "", "-999", -1, -1 },
1057: { "xyz%*Ff", "", "-999", -1, -1 },
1058:
1059: { "%Ff", "xyz", "0", 0 },
1060:
1061: /* various non-empty but invalid */
1062: { "%Ff", "-", "-999", 0 },
1063: { "%Ff", "+", "-999", 0 },
1064: { "xyz%Ff", "xyz-", "-999", 0 },
1065: { "xyz%Ff", "xyz+", "-999", 0 },
1066: { "xyz%Ff", "-.", "-999", 0 },
1067: { "xyz%Ff", "+.", "-999", 0 },
1068: { "xyz%Ff", ".e", "-999", 0 },
1069: { "xyz%Ff", "-.e", "-999", 0 },
1070: { "xyz%Ff", "+.e", "-999", 0 },
1071: { "xyz%Ff", ".E", "-999", 0 },
1072: { "xyz%Ff", "-.E", "-999", 0 },
1073: { "xyz%Ff", "+.E", "-999", 0 },
1074: { "xyz%Ff", ".e123", "-999", 0 },
1075: { "xyz%Ff", "-.e123", "-999", 0 },
1076: { "xyz%Ff", "+.e123", "-999", 0 },
1077:
1078: };
1079:
1080: int i, j, ignore, got_ret, want_ret, got_upto, want_upto;
1081: mpf_t got, want;
1082: double got_d;
1083: long want_ftell;
1084: int error = 0;
1085: fun_t fun;
1086: const char *name;
1087: char fmt[128];
1088:
1089: mpf_init (got);
1090: mpf_init (want);
1091:
1092: for (i = 0; i < numberof (data); i++)
1093: {
1094: mpf_set_str_or_abort (want, data[i].want, 0);
1095:
1096: ASSERT_ALWAYS (strlen (data[i].fmt) + 2 < sizeof (fmt));
1097: strcpy (fmt, data[i].fmt);
1098: strcat (fmt, "%n");
1099:
1100: ignore = (strchr (fmt, '*') != NULL);
1101:
1102: for (j = 0; j <= 3; j++)
1103: {
1104: want_ret = data[i].ret;
1105:
1106: want_ftell = data[i].ftell;
1107: if (want_ftell == -1)
1108: want_ftell = strlen (data[i].input);
1109: want_upto = want_ftell;
1110:
1111: if (want_ret == -1 || (want_ret == 0 && ! ignore))
1112: {
1113: want_ftell = -1;
1114: want_upto = -555;
1115: }
1116:
1117: switch (j) {
1118: case 0:
1119: name = "gmp_sscanf";
1120: fun = fun_gmp_sscanf;
1121: break;
1122: case 1:
1123: name = "gmp_fscanf";
1124: fun = fun_gmp_fscanf;
1125: break;
1126: case 2:
1127: if (! libc_scanf_convert (fmt))
1128: continue;
1129: name = "standard sscanf";
1130: fun = fun_sscanf;
1131: break;
1132: case 3:
1133: if (! libc_scanf_convert (fmt))
1134: continue;
1135: name = "standard fscanf";
1136: fun = fun_fscanf;
1137: break;
1138: default:
1139: ASSERT_ALWAYS (0);
1140: break;
1141: }
1142:
1143: got_upto = -555;
1144: got_ftell = -1;
1145:
1146: switch (j) {
1147: case 0:
1148: case 1:
1149: mpf_set_si (got, -999L);
1150: if (ignore)
1151: got_ret = (*fun) (data[i].input, fmt, &got_upto, NULL);
1152: else
1153: got_ret = (*fun) (data[i].input, fmt, got, &got_upto);
1154: break;
1155: case 2:
1156: case 3:
1157: got_d = -999L;
1158: if (ignore)
1159: got_ret = (*fun) (data[i].input, fmt, &got_upto, NULL);
1160: else
1161: got_ret = (*fun) (data[i].input, fmt, &got_d, &got_upto);
1162: mpf_set_d (got, got_d);
1163: break;
1164: default:
1165: ASSERT_ALWAYS (0);
1166: break;
1167: }
1168:
1169: MPF_CHECK_FORMAT (got);
1170:
1171: if (got_ret != want_ret)
1172: {
1173: printf ("%s wrong return value\n", name);
1174: error = 1;
1175: }
1176: if (want_ret == 1 && mpf_cmp (want, got) != 0)
1177: {
1178: printf ("%s wrong result\n", name);
1179: error = 1;
1180: }
1181: if (got_upto != want_upto)
1182: {
1183: printf ("%s wrong upto\n", name);
1184: error = 1;
1185: }
1186: if (got_ftell != -1 && want_ftell != -1 && got_ftell != want_ftell)
1187: {
1188: printf ("%s wrong ftell\n", name);
1189: error = 1;
1190: }
1191: if (error)
1192: {
1193: printf (" fmt \"%s\"\n", data[i].fmt);
1194: printf (" input \"%s\"\n", data[i].input);
1195: printf (" ret want=%d\n", want_ret);
1196: printf (" got =%d\n", got_ret);
1197: mpf_trace (" value want", want);
1198: mpf_trace (" got ", got);
1199: printf (" upto want=%d\n", want_upto);
1200: printf (" got =%d\n", got_upto);
1201: if (got_ftell != -1)
1202: {
1203: printf (" ftell want =%ld\n", want_ftell);
1204: printf (" got =%ld\n", got_ftell);
1205: }
1206: abort ();
1207: }
1208: }
1209: }
1210:
1211: mpf_clear (got);
1212: mpf_clear (want);
1213: }
1214:
1215:
1216: void
1217: check_n (void)
1218: {
1219: int ret;
1220:
1221: /* %n suppressed */
1222: {
1223: int n = 123;
1224: gmp_sscanf (" ", " %*n", &n);
1225: ASSERT_ALWAYS (n == 123);
1226: }
1227: {
1228: int n = 123;
1229: fromstring_gmp_fscanf (" ", " %*n", &n);
1230: ASSERT_ALWAYS (n == 123);
1231: }
1232:
1233:
1234: #define CHECK_N(type, string) \
1235: do { \
1236: type x[2]; \
1237: char fmt[128]; \
1238: int ret; \
1239: \
1240: x[0] = ~ (type) 0; \
1241: x[1] = ~ (type) 0; \
1242: sprintf (fmt, "abc%%%sn", string); \
1243: ret = gmp_sscanf ("abc", fmt, &x[0]); \
1244: \
1245: ASSERT_ALWAYS (ret == 0); \
1246: \
1247: /* should write whole of x[0] and none of x[1] */ \
1248: ASSERT_ALWAYS (x[0] == 3); \
1249: ASSERT_ALWAYS (x[1] == (type) ~ (type) 0); \
1250: \
1251: } while (0)
1252:
1253: CHECK_N (char, "hh");
1254: CHECK_N (long, "l");
1255: #if HAVE_LONG_LONG
1256: CHECK_N (long long, "L");
1257: #endif
1258: #if HAVE_INTMAX_T
1259: CHECK_N (intmax_t, "j");
1260: #endif
1261: #if HAVE_PTRDIFF_T
1262: CHECK_N (ptrdiff_t, "t");
1263: #endif
1264: CHECK_N (short, "h");
1265: CHECK_N (size_t, "z");
1266:
1267: /* %Zn */
1268: {
1269: mpz_t x[2];
1270: mpz_init_set_si (x[0], -987L);
1271: mpz_init_set_si (x[1], 654L);
1272: ret = gmp_sscanf ("xyz ", "xyz%Zn", x[0]);
1273: MPZ_CHECK_FORMAT (x[0]);
1274: MPZ_CHECK_FORMAT (x[1]);
1275: ASSERT_ALWAYS (ret == 0);
1276: ASSERT_ALWAYS (mpz_cmp_ui (x[0], 3L) == 0);
1277: ASSERT_ALWAYS (mpz_cmp_ui (x[1], 654L) == 0);
1278: mpz_clear (x[0]);
1279: mpz_clear (x[1]);
1280: }
1281: {
1282: mpz_t x;
1283: mpz_init (x);
1284: ret = fromstring_gmp_fscanf ("xyz ", "xyz%Zn", x);
1285: ASSERT_ALWAYS (ret == 0);
1286: ASSERT_ALWAYS (mpz_cmp_ui (x, 3L) == 0);
1287: mpz_clear (x);
1288: }
1289:
1290: /* %Qn */
1291: {
1292: mpq_t x[2];
1293: mpq_init (x[0]);
1294: mpq_init (x[1]);
1295: mpq_set_ui (x[0], -987L, 654L);
1296: mpq_set_ui (x[1], 4115L, 226L);
1297: ret = gmp_sscanf ("xyz ", "xyz%Qn", x[0]);
1298: MPQ_CHECK_FORMAT (x[0]);
1299: MPQ_CHECK_FORMAT (x[1]);
1300: ASSERT_ALWAYS (ret == 0);
1301: ASSERT_ALWAYS (mpq_cmp_ui (x[0], 3L, 1L) == 0);
1302: ASSERT_ALWAYS (mpq_cmp_ui (x[1], 4115L, 226L) == 0);
1303: mpq_clear (x[0]);
1304: mpq_clear (x[1]);
1305: }
1306: {
1307: mpq_t x;
1308: mpq_init (x);
1309: ret = fromstring_gmp_fscanf ("xyz ", "xyz%Qn", x);
1310: ASSERT_ALWAYS (ret == 0);
1311: ASSERT_ALWAYS (mpq_cmp_ui (x, 3L, 1L) == 0);
1312: mpq_clear (x);
1313: }
1314:
1315: /* %Fn */
1316: {
1317: mpf_t x[2];
1318: mpf_init (x[0]);
1319: mpf_init (x[1]);
1320: mpf_set_ui (x[0], -987L);
1321: mpf_set_ui (x[1], 654L);
1322: ret = gmp_sscanf ("xyz ", "xyz%Fn", x[0]);
1323: MPF_CHECK_FORMAT (x[0]);
1324: MPF_CHECK_FORMAT (x[1]);
1325: ASSERT_ALWAYS (ret == 0);
1326: ASSERT_ALWAYS (mpf_cmp_ui (x[0], 3L) == 0);
1327: ASSERT_ALWAYS (mpf_cmp_ui (x[1], 654L) == 0);
1328: mpf_clear (x[0]);
1329: mpf_clear (x[1]);
1330: }
1331: {
1332: mpf_t x;
1333: mpf_init (x);
1334: ret = fromstring_gmp_fscanf ("xyz ", "xyz%Fn", x);
1335: ASSERT_ALWAYS (ret == 0);
1336: ASSERT_ALWAYS (mpf_cmp_ui (x, 3L) == 0);
1337: mpf_clear (x);
1338: }
1339: }
1340:
1341:
1342: void
1343: check_misc (void)
1344: {
1345: int ret, cmp;
1346: {
1347: int a=9, b=8, c=7, n=66;
1348: mpz_t z;
1349: mpz_init (z);
1350: ret = gmp_sscanf ("1 2 3 4", "%d %d %d %Zd%n",
1351: &a, &b, &c, z, &n);
1352: ASSERT_ALWAYS (ret == 4);
1353: ASSERT_ALWAYS (a == 1);
1354: ASSERT_ALWAYS (b == 2);
1355: ASSERT_ALWAYS (c == 3);
1356: ASSERT_ALWAYS (n == 7);
1357: ASSERT_ALWAYS (mpz_cmp_ui (z, 4L) == 0);
1358: mpz_clear (z);
1359: }
1360: {
1361: int a=9, b=8, c=7, n=66;
1362: mpz_t z;
1363: mpz_init (z);
1364: ret = fromstring_gmp_fscanf ("1 2 3 4", "%d %d %d %Zd%n",
1365: &a, &b, &c, z, &n);
1366: ASSERT_ALWAYS (ret == 4);
1367: ASSERT_ALWAYS (a == 1);
1368: ASSERT_ALWAYS (b == 2);
1369: ASSERT_ALWAYS (c == 3);
1370: ASSERT_ALWAYS (mpz_cmp_ui (z, 4L) == 0);
1371: ASSERT_ALWAYS (n == 7);
1372: ASSERT_ALWAYS (got_ftell == 7);
1373: mpz_clear (z);
1374: }
1375:
1376: {
1377: int a=9, n=8;
1378: mpz_t z;
1379: mpz_init (z);
1380: ret = gmp_sscanf ("1 2 3 4", "%d %*d %*d %Zd%n", &a, z, &n);
1381: ASSERT_ALWAYS (ret == 2);
1382: ASSERT_ALWAYS (a == 1);
1383: ASSERT_ALWAYS (mpz_cmp_ui (z, 4L) == 0);
1384: ASSERT_ALWAYS (n == 7);
1385: mpz_clear (z);
1386: }
1387: {
1388: int a=9, n=8;
1389: mpz_t z;
1390: mpz_init (z);
1391: ret = fromstring_gmp_fscanf ("1 2 3 4", "%d %*d %*d %Zd%n",
1392: &a, z, &n);
1393: ASSERT_ALWAYS (ret == 2);
1394: ASSERT_ALWAYS (a == 1);
1395: ASSERT_ALWAYS (mpz_cmp_ui (z, 4L) == 0);
1396: ASSERT_ALWAYS (n == 7);
1397: ASSERT_ALWAYS (got_ftell == 7);
1398: mpz_clear (z);
1399: }
1400:
1401: /* -1 for no matching */
1402: {
1403: char buf[128];
1404: ret = gmp_sscanf (" ", "%s", buf);
1405: ASSERT_ALWAYS (ret == -1);
1406: ret = fromstring_gmp_fscanf (" ", "%s", buf);
1407: ASSERT_ALWAYS (ret == -1);
1408: if (option_libc_scanf)
1409: {
1410: ret = sscanf (" ", "%s", buf);
1411: ASSERT_ALWAYS (ret == -1);
1412: ret = fun_fscanf (" ", "%s", buf, NULL);
1413: ASSERT_ALWAYS (ret == -1);
1414: }
1415: }
1416:
1417: /* suppressed field, then eof */
1418: {
1419: int x;
1420: ret = gmp_sscanf ("123", "%*d%d", &x);
1421: ASSERT_ALWAYS (ret == -1);
1422: ret = fromstring_gmp_fscanf ("123", "%*d%d", &x);
1423: ASSERT_ALWAYS (ret == -1);
1424: if (option_libc_scanf)
1425: {
1426: ret = sscanf ("123", "%*d%d", &x);
1427: ASSERT_ALWAYS (ret == -1);
1428: ret = fun_fscanf ("123", "%*d%d", &x, NULL);
1429: ASSERT_ALWAYS (ret == -1);
1430: }
1431: }
1432: {
1433: mpz_t x;
1434: mpz_init (x);
1435: ret = gmp_sscanf ("123", "%*Zd%Zd", x);
1436: ASSERT_ALWAYS (ret == -1);
1437: ret = fromstring_gmp_fscanf ("123", "%*Zd%Zd", x);
1438: ASSERT_ALWAYS (ret == -1);
1439: mpz_clear (x);
1440: }
1441:
1442: /* %[...], glibc only */
1443: #ifdef __GLIBC__
1444: {
1445: char buf[128];
1446: int n = -1;
1447: buf[0] = '\0';
1448: ret = gmp_sscanf ("abcdefgh", "%[a-d]ef%n", buf, &n);
1449: ASSERT_ALWAYS (ret == 1);
1450: cmp = strcmp (buf, "abcd");
1451: ASSERT_ALWAYS (cmp == 0);
1452: ASSERT_ALWAYS (n == 6);
1453: }
1454: {
1455: char buf[128];
1456: int n = -1;
1457: buf[0] = '\0';
1458: ret = gmp_sscanf ("xyza", "%[^a]a%n", buf, &n);
1459: ASSERT_ALWAYS (ret == 1);
1460: cmp = strcmp (buf, "xyz");
1461: ASSERT_ALWAYS (cmp == 0);
1462: ASSERT_ALWAYS (n == 4);
1463: }
1464: {
1465: char buf[128];
1466: int n = -1;
1467: buf[0] = '\0';
1468: ret = gmp_sscanf ("ab]ab]", "%[]ab]%n", buf, &n);
1469: ASSERT_ALWAYS (ret == 1);
1470: cmp = strcmp (buf, "ab]ab]");
1471: ASSERT_ALWAYS (cmp == 0);
1472: ASSERT_ALWAYS (n == 6);
1473: }
1474: {
1475: char buf[128];
1476: int n = -1;
1477: buf[0] = '\0';
1478: ret = gmp_sscanf ("xyzb", "%[^]ab]b%n", buf, &n);
1479: ASSERT_ALWAYS (ret == 1);
1480: cmp = strcmp (buf, "xyz");
1481: ASSERT_ALWAYS (cmp == 0);
1482: ASSERT_ALWAYS (n == 4);
1483: }
1484: #endif
1485:
1486: /* %zd etc won't be accepted by sscanf on old systems, and running
1487: something to see if they work might be bad, so only try it on glibc,
1488: and only on a new enough version (glibc 2.0 doesn't have %zd) */
1489: #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 0)
1490: {
1491: mpz_t z;
1492: size_t s = -1;
1493: mpz_init (z);
1494: ret = gmp_sscanf ("456 789", "%zd %Zd", &s, z);
1495: ASSERT_ALWAYS (ret == 2);
1496: ASSERT_ALWAYS (s == 456);
1497: ASSERT_ALWAYS (mpz_cmp_ui (z, 789L) == 0);
1498: mpz_clear (z);
1499: }
1500: {
1501: mpz_t z;
1502: ptrdiff_t d = -1;
1503: mpz_init (z);
1504: ret = gmp_sscanf ("456 789", "%td %Zd", &d, z);
1505: ASSERT_ALWAYS (ret == 2);
1506: ASSERT_ALWAYS (d == 456);
1507: ASSERT_ALWAYS (mpz_cmp_ui (z, 789L) == 0);
1508: mpz_clear (z);
1509: }
1510: {
1511: mpz_t z;
1512: long long ll = -1;
1513: mpz_init (z);
1514: ret = gmp_sscanf ("456 789", "%Ld %Zd", &ll, z);
1515: ASSERT_ALWAYS (ret == 2);
1516: ASSERT_ALWAYS (ll == 456);
1517: ASSERT_ALWAYS (mpz_cmp_ui (z, 789L) == 0);
1518: mpz_clear (z);
1519: }
1520: #endif
1521: }
1522:
1523: int
1524: main (int argc, char *argv[])
1525: {
1526: if (argc > 1 && strcmp (argv[1], "-s") == 0)
1527: option_libc_scanf = 1;
1528:
1529: tests_start ();
1530:
1531: check_z ();
1532: check_q ();
1533: check_f ();
1534: check_n ();
1535: check_misc ();
1536:
1537: unlink (TEMPFILE);
1538: tests_end ();
1539: exit (0);
1540: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>