Annotation of OpenXM_contrib/gmp/tests/misc/t-scanf.c, Revision 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>