1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/genericopenlibs/cstdlib/LSTDIO/VFSCANF.C Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,840 @@
1.4 +/* VFSCANF.C
1.5 + *
1.6 + * Portions Copyright (c) 1990-2004 Nokia Corporation and/or its subsidiary(-ies).
1.7 + * All rights reserved.
1.8 + */
1.9 +
1.10 +/* No user fns here. Pesch 15apr92. */
1.11 +
1.12 +/*
1.13 + * Copyright (c) 1990 The Regents of the University of California.
1.14 + * All rights reserved.
1.15 + *
1.16 + * Redistribution and use in source and binary forms are permitted
1.17 + * provided that the above copyright notice and this paragraph are
1.18 + * duplicated in all such forms and that any documentation,
1.19 + * advertising materials, and other materials related to such
1.20 + * distribution and use acknowledge that the software was developed
1.21 + * by the University of California, Berkeley. The name of the
1.22 + * University may not be used to endorse or promote products derived
1.23 + * from this software without specific prior written permission.
1.24 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1.25 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1.26 + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1.27 + */
1.28 +
1.29 +#include <_ansi.h>
1.30 +#include <ctype.h>
1.31 +#include <stdio.h>
1.32 +#include <stdlib.h>
1.33 +#include <stdarg.h>
1.34 +#include "LOCAL.H"
1.35 +
1.36 +#include "FLOATIO.H"
1.37 +#define BUF (MAXEXP+MAXFRACT+3) /* 3 = sign + decimal point + NUL */
1.38 +
1.39 +/*
1.40 + * Flags used during conversion.
1.41 + */
1.42 +
1.43 +#define LONG 0x01 /* l: long or double */
1.44 +#define LONGDBL 0x02 /* L: long double; unimplemented */
1.45 +#define SHORT 0x04 /* h: short */
1.46 +#define SUPPRESS 0x08 /* suppress assignment */
1.47 +#define POINTER 0x10 /* weird %p pointer (`fake hex') */
1.48 +#define NOSKIP 0x20 /* do not skip blanks */
1.49 +
1.50 +/*
1.51 + * The following are used in numeric conversions only:
1.52 + * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point;
1.53 + * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral.
1.54 + */
1.55 +
1.56 +#define SIGNOK 0x40 /* +/- is (still) legal */
1.57 +#define NDIGITS 0x80 /* no digits detected */
1.58 +
1.59 +#define DPTOK 0x100 /* (float) decimal point is still legal */
1.60 +#define EXPOK 0x200 /* (float) exponent (e+3, etc) still legal */
1.61 +
1.62 +#define PFXOK 0x100 /* 0x prefix is (still) legal */
1.63 +#define NZDIGITS 0x200 /* no zero digits detected */
1.64 +
1.65 +/*
1.66 + * Conversion types.
1.67 + */
1.68 +
1.69 +#define CT_CHAR 0 /* %c conversion */
1.70 +#define CT_CCL 1 /* %[...] conversion */
1.71 +#define CT_STRING 2 /* %s conversion */
1.72 +#define CT_INT 3 /* integer, i.e., strtol or strtoul */
1.73 +#define CT_FLOAT 4 /* floating, i.e., strtod */
1.74 +
1.75 +#define u_char char
1.76 +#define u_long unsigned long
1.77 +
1.78 +/*static*/ u_char *__sccl (register char *tab,register u_char *fmt);
1.79 +
1.80 +/*
1.81 + * vfscanf
1.82 + */
1.83 +
1.84 +#define BufferEmpty (fp->_r <= 0 && __srefill(fp))
1.85 +
1.86 +int
1.87 +__svfscanf (register FILE *fp,char const *fmt0, va_list ap)
1.88 +{
1.89 + register u_char *fmt = (u_char *) fmt0;
1.90 + register int c; /* character from format, or conversion */
1.91 + register size_t width; /* field width, or 0 */
1.92 + register char *p; /* points into all kinds of strings */
1.93 + register int n; /* handy integer */
1.94 + register int flags; /* flags as defined above */
1.95 + register char *p0; /* saves original value of p when necessary */
1.96 + int nassigned; /* number of fields assigned */
1.97 + int nread; /* number of characters consumed from fp */
1.98 + int base = 0; /* base argument to strtol/strtoul */
1.99 +
1.100 + u_long (*ccfn) (const char *_n, char **_end_PTR, int _base) = 0; /* conversion function (strtol/strtoul) */
1.101 + char ccltab[256]; /* character class table for %[...] */
1.102 + char buf[BUF]; /* buffer for numeric conversions */
1.103 +
1.104 + short *sp;
1.105 + int *ip;
1.106 + float *flp;
1.107 + double *dp;
1.108 + long *lp;
1.109 +
1.110 + /* `basefix' is used to avoid `if' tests in the integer scanner */
1.111 + static const short basefix[17] =
1.112 + {10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
1.113 +
1.114 + nassigned = 0;
1.115 + nread = 0;
1.116 + for (;;)
1.117 + {
1.118 + c = *fmt++;
1.119 + if (c == 0)
1.120 + return nassigned;
1.121 + if (isspace (c))
1.122 + {
1.123 + for (;;)
1.124 + {
1.125 + if (BufferEmpty)
1.126 + return nassigned;
1.127 + if (!isspace (*fp->_p))
1.128 + break;
1.129 + nread++, fp->_r--, fp->_p++;
1.130 + }
1.131 + continue;
1.132 + }
1.133 + if (c != '%')
1.134 + goto literal;
1.135 + width = 0;
1.136 + flags = 0;
1.137 +
1.138 + /*
1.139 + * switch on the format. continue if done; break once format
1.140 + * type is derived.
1.141 + */
1.142 +
1.143 + again:
1.144 + c = *fmt++;
1.145 +
1.146 + switch (c)
1.147 + {
1.148 + case '%':
1.149 + literal:
1.150 + if (BufferEmpty)
1.151 + goto input_failure;
1.152 + if (*fp->_p != c)
1.153 + goto match_failure;
1.154 + fp->_r--, fp->_p++;
1.155 + nread++;
1.156 + continue;
1.157 +
1.158 + case '*':
1.159 + flags |= SUPPRESS;
1.160 + goto again;
1.161 + case 'l':
1.162 + flags |= LONG;
1.163 + goto again;
1.164 + case 'L':
1.165 + /* not supported flags |= LONGDBL; */
1.166 + goto again;
1.167 + case 'h':
1.168 + flags |= SHORT;
1.169 + goto again;
1.170 +
1.171 + case '0':
1.172 + case '1':
1.173 + case '2':
1.174 + case '3':
1.175 + case '4':
1.176 + case '5':
1.177 + case '6':
1.178 + case '7':
1.179 + case '8':
1.180 + case '9':
1.181 + width = width * 10 + c - '0';
1.182 + goto again;
1.183 +
1.184 + /*
1.185 + * Conversions. Those marked `compat' are for
1.186 + * 4.[123]BSD compatibility.
1.187 + *
1.188 + * (According to ANSI, E and X formats are supposed to
1.189 + * the same as e and x. Sorry about that.)
1.190 + */
1.191 +
1.192 + case 'D': /* compat */
1.193 + flags |= LONG;
1.194 + /* FALLTHROUGH */
1.195 + case 'd':
1.196 + c = CT_INT;
1.197 + ccfn = (u_long (*)(const char *_n, char **_end_PTR, int _base))strtol;
1.198 + base = 10;
1.199 + break;
1.200 +
1.201 + case 'i':
1.202 + c = CT_INT;
1.203 + ccfn = (u_long (*)(const char *_n, char **_end_PTR, int _base))strtol;
1.204 + base = 0;
1.205 + break;
1.206 +
1.207 + case 'O': /* compat */
1.208 + flags |= LONG;
1.209 + /* FALLTHROUGH */
1.210 + case 'o':
1.211 + c = CT_INT;
1.212 + ccfn = (u_long (*)(const char *_n, char **_end_PTR, int _base))strtoul;
1.213 + base = 8;
1.214 + break;
1.215 +
1.216 + case 'u':
1.217 + c = CT_INT;
1.218 + ccfn = (u_long (*)(const char *_n, char **_end_PTR, int _base))strtoul;
1.219 + base = 10;
1.220 + break;
1.221 +
1.222 + case 'X': /* compat XXX */
1.223 + case 'x':
1.224 + flags |= PFXOK; /* enable 0x prefixing */
1.225 + c = CT_INT;
1.226 + ccfn = (u_long (*)(const char *_n, char **_end_PTR, int _base))strtoul;
1.227 + base = 16;
1.228 + break;
1.229 +
1.230 + case 'E': /* compat XXX */
1.231 + case 'G': /* compat XXX */
1.232 +/* ANSI says that E,G and X behave the same way as e,g,x */
1.233 + /* FALLTHROUGH */
1.234 + case 'e':
1.235 + case 'f':
1.236 + case 'g':
1.237 + c = CT_FLOAT;
1.238 + break;
1.239 +
1.240 + case 's':
1.241 + c = CT_STRING;
1.242 + break;
1.243 +
1.244 + case '[':
1.245 + fmt = __sccl (ccltab, fmt);
1.246 + flags |= NOSKIP;
1.247 + c = CT_CCL;
1.248 + break;
1.249 +
1.250 + case 'c':
1.251 + flags |= NOSKIP;
1.252 + c = CT_CHAR;
1.253 + break;
1.254 +
1.255 + case 'p': /* pointer format is like hex */
1.256 + flags |= POINTER | PFXOK;
1.257 + c = CT_INT;
1.258 + ccfn = (u_long (*)(const char *_n, char **_end_PTR, int _base))strtoul;
1.259 + base = 16;
1.260 + break;
1.261 +
1.262 + case 'n':
1.263 + if (flags & SUPPRESS) /* ??? */
1.264 + continue;
1.265 + if (flags & SHORT)
1.266 + {
1.267 + sp = va_arg (ap, short *);
1.268 + *sp = (short)nread;
1.269 + }
1.270 + else if (flags & LONG)
1.271 + {
1.272 + lp = va_arg (ap, long *);
1.273 + *lp = nread;
1.274 + }
1.275 + else
1.276 + {
1.277 + ip = va_arg (ap, int *);
1.278 + *ip = nread;
1.279 + }
1.280 + continue;
1.281 +
1.282 + /*
1.283 + * Disgusting backwards compatibility hacks. XXX
1.284 + */
1.285 + case '\0': /* compat */
1.286 + return EOF;
1.287 +
1.288 + default: /* compat */
1.289 + if (isupper (c))
1.290 + flags |= LONG;
1.291 + c = CT_INT;
1.292 + ccfn = (u_long (*)(const char *_n, char **_end_PTR, int _base))strtol;
1.293 + base = 10;
1.294 + break;
1.295 + }
1.296 +
1.297 + /*
1.298 + * We have a conversion that requires input.
1.299 + */
1.300 + if (BufferEmpty)
1.301 + goto input_failure;
1.302 +
1.303 + /*
1.304 + * Consume leading white space, except for formats that
1.305 + * suppress this.
1.306 + */
1.307 + if ((flags & NOSKIP) == 0)
1.308 + {
1.309 + while (isspace (*fp->_p))
1.310 + {
1.311 + nread++;
1.312 + if (--fp->_r > 0)
1.313 + fp->_p++;
1.314 + else
1.315 + if (__srefill (fp))
1.316 + goto input_failure;
1.317 + }
1.318 + /*
1.319 + * Note that there is at least one character in the
1.320 + * buffer, so conversions that do not set NOSKIP ca
1.321 + * no longer result in an input failure.
1.322 + */
1.323 + }
1.324 +
1.325 + /*
1.326 + * Do the conversion.
1.327 + */
1.328 + switch (c)
1.329 + {
1.330 +
1.331 + case CT_CHAR:
1.332 + /* scan arbitrary characters (sets NOSKIP) */
1.333 + if (width == 0)
1.334 + width = 1;
1.335 + if (flags & SUPPRESS)
1.336 + {
1.337 + size_t sum = 0;
1.338 +
1.339 + for (;;)
1.340 + {
1.341 + if ((n = fp->_r) < (int)width)
1.342 + {
1.343 + sum += n;
1.344 + width -= n;
1.345 + fp->_p += n;
1.346 + if (__srefill (fp))
1.347 + {
1.348 + if (sum == 0)
1.349 + goto input_failure;
1.350 + break;
1.351 + }
1.352 + }
1.353 + else
1.354 + {
1.355 + sum += width;
1.356 + fp->_r -= width;
1.357 + fp->_p += width;
1.358 + break;
1.359 + }
1.360 + }
1.361 + nread += sum;
1.362 + }
1.363 + else
1.364 + {
1.365 + size_t r = fread ((void*) va_arg (ap, char *), 1, width, fp);
1.366 +
1.367 + if (r == 0)
1.368 + goto input_failure;
1.369 + nread += r;
1.370 + nassigned++;
1.371 + }
1.372 + break;
1.373 +
1.374 + case CT_CCL:
1.375 + /* scan a (nonempty) character class (sets NOSKIP) */
1.376 + if (width == 0)
1.377 + width = (unsigned long)(~0); /* `infinity' */
1.378 + /* take only those things in the class */
1.379 + if (flags & SUPPRESS)
1.380 + {
1.381 + n = 0;
1.382 + while (ccltab[*fp->_p])
1.383 + {
1.384 + n++, fp->_r--, fp->_p++;
1.385 + if (--width == 0)
1.386 + break;
1.387 + if (BufferEmpty)
1.388 + {
1.389 + if (n == 0)
1.390 + goto input_failure;
1.391 + break;
1.392 + }
1.393 + }
1.394 + if (n == 0)
1.395 + goto match_failure;
1.396 + }
1.397 + else
1.398 + {
1.399 + p0 = p = va_arg (ap, char *);
1.400 + while (ccltab[*fp->_p])
1.401 + {
1.402 + fp->_r--;
1.403 + *p++ = *fp->_p++;
1.404 + if (--width == 0)
1.405 + break;
1.406 + if (BufferEmpty)
1.407 + {
1.408 + if (p == p0)
1.409 + goto input_failure;
1.410 + break;
1.411 + }
1.412 + }
1.413 + n = p - p0;
1.414 + if (n == 0)
1.415 + goto match_failure;
1.416 + *p = 0;
1.417 + nassigned++;
1.418 + }
1.419 + nread += n;
1.420 + break;
1.421 +
1.422 + case CT_STRING:
1.423 + /* like CCL, but zero-length string OK, & no NOSKIP */
1.424 + if (width == 0)
1.425 + width = (unsigned long)(~0);
1.426 + if (flags & SUPPRESS)
1.427 + {
1.428 + n = 0;
1.429 + while (!isspace (*fp->_p))
1.430 + {
1.431 + n++, fp->_r--, fp->_p++;
1.432 + if (--width == 0)
1.433 + break;
1.434 + if (BufferEmpty)
1.435 + break;
1.436 + }
1.437 + nread += n;
1.438 + }
1.439 + else
1.440 + {
1.441 + p0 = p = va_arg (ap, char *);
1.442 + while (!isspace (*fp->_p))
1.443 + {
1.444 + fp->_r--;
1.445 + *p++ = *fp->_p++;
1.446 + if (--width == 0)
1.447 + break;
1.448 + if (BufferEmpty)
1.449 + break;
1.450 + }
1.451 + *p = 0;
1.452 + nread += p - p0;
1.453 + nassigned++;
1.454 + }
1.455 + continue;
1.456 +
1.457 + case CT_INT:
1.458 + /* scan an integer as if by strtol/strtoul */
1.459 +#ifdef hardway
1.460 + if (width == 0 || width > sizeof (buf) - 1)
1.461 + width = sizeof (buf) - 1;
1.462 +#else
1.463 + /* size_t is unsigned, hence this optimisation */
1.464 + if (--width > sizeof (buf) - 2)
1.465 + width = sizeof (buf) - 2;
1.466 + width++;
1.467 +#endif
1.468 + flags |= SIGNOK | NDIGITS | NZDIGITS;
1.469 + for (p = buf; width; width--)
1.470 + {
1.471 + c = *fp->_p;
1.472 + /*
1.473 + * Switch on the character; `goto ok' if we
1.474 + * accept it as a part of number.
1.475 + */
1.476 + switch (c)
1.477 + {
1.478 + /*
1.479 + * The digit 0 is always legal, but is special.
1.480 + * For %i conversions, if no digits (zero or nonzero)
1.481 + * have been scanned (only signs), we will have base==0.
1.482 + * In that case, we should set it to 8 and enable 0x
1.483 + * prefixing. Also, if we have not scanned zero digits
1.484 + * before this, do not turn off prefixing (someone else
1.485 + * will turn it off if we have scanned any nonzero digits).
1.486 + */
1.487 + case '0':
1.488 + if (base == 0)
1.489 + {
1.490 + base = 8;
1.491 + flags |= PFXOK;
1.492 + }
1.493 + if (flags & NZDIGITS)
1.494 + flags &= ~(SIGNOK | NZDIGITS | NDIGITS);
1.495 + else
1.496 + flags &= ~(SIGNOK | PFXOK | NDIGITS);
1.497 + goto ok;
1.498 +
1.499 + /* 1 through 7 always legal */
1.500 + case '1':
1.501 + case '2':
1.502 + case '3':
1.503 + case '4':
1.504 + case '5':
1.505 + case '6':
1.506 + case '7':
1.507 + base = basefix[base];
1.508 + flags &= ~(SIGNOK | PFXOK | NDIGITS);
1.509 + goto ok;
1.510 +
1.511 + /* digits 8 and 9 ok iff decimal or hex */
1.512 + case '8':
1.513 + case '9':
1.514 + base = basefix[base];
1.515 + if (base <= 8)
1.516 + break; /* not legal here */
1.517 + flags &= ~(SIGNOK | PFXOK | NDIGITS);
1.518 + goto ok;
1.519 +
1.520 + /* letters ok iff hex */
1.521 + case 'A':
1.522 + case 'B':
1.523 + case 'C':
1.524 + case 'D':
1.525 + case 'E':
1.526 + case 'F':
1.527 + case 'a':
1.528 + case 'b':
1.529 + case 'c':
1.530 + case 'd':
1.531 + case 'e':
1.532 + case 'f':
1.533 + /* no need to fix base here */
1.534 + if (base <= 10)
1.535 + break; /* not legal here */
1.536 + flags &= ~(SIGNOK | PFXOK | NDIGITS);
1.537 + goto ok;
1.538 +
1.539 + /* sign ok only as first character */
1.540 + case '+':
1.541 + case '-':
1.542 + if (flags & SIGNOK)
1.543 + {
1.544 + flags &= ~SIGNOK;
1.545 + goto ok;
1.546 + }
1.547 + break;
1.548 +
1.549 + /* x ok iff flag still set & 2nd char */
1.550 + case 'x':
1.551 + case 'X':
1.552 + if (flags & PFXOK && p == buf + 1)
1.553 + {
1.554 + base = 16;/* if %i */
1.555 + flags &= ~PFXOK;
1.556 + goto ok;
1.557 + }
1.558 + break;
1.559 + }
1.560 +
1.561 + /*
1.562 + * If we got here, c is not a legal character
1.563 + * for a number. Stop accumulating digits.
1.564 + */
1.565 + break;
1.566 + ok:
1.567 + /*
1.568 + * c is legal: store it and look at the next.
1.569 + */
1.570 + *p++ = (char)c;
1.571 + if (--fp->_r > 0)
1.572 + fp->_p++;
1.573 + else
1.574 + if (__srefill (fp))
1.575 + break; /* EOF */
1.576 + }
1.577 + /*
1.578 + * If we had only a sign, it is no good; push back the sign.
1.579 + * If the number ends in `x', it was [sign] '0' 'x', so push back
1.580 + * the x and treat it as [sign] '0'.
1.581 + */
1.582 + if (flags & NDIGITS)
1.583 + {
1.584 + if (p > buf)
1.585 + (void) ungetc (*(u_char *)-- p, fp);
1.586 + goto match_failure;
1.587 + }
1.588 + c = ((u_char *) p)[-1];
1.589 + if (c == 'x' || c == 'X')
1.590 + {
1.591 + --p;
1.592 + /*(void)*/ ungetc (c, fp);
1.593 + }
1.594 + if ((flags & SUPPRESS) == 0)
1.595 + {
1.596 + u_long res;
1.597 +
1.598 + *p = 0;
1.599 + res = (*ccfn) (buf, (char **) NULL, base);
1.600 + if (flags & POINTER)
1.601 + *(va_arg (ap, void* *)) = (void*) res;
1.602 + else if (flags & SHORT)
1.603 + {
1.604 + sp = va_arg (ap, short *);
1.605 + *sp = (short)res;
1.606 + }
1.607 + else if (flags & LONG)
1.608 + {
1.609 + lp = va_arg (ap, long *);
1.610 + *lp = res;
1.611 + }
1.612 + else
1.613 + {
1.614 + ip = va_arg (ap, int *);
1.615 + *ip = res;
1.616 + }
1.617 + nassigned++;
1.618 + }
1.619 + nread += p - buf;
1.620 + break;
1.621 +
1.622 + case CT_FLOAT:
1.623 + /* scan a floating point number as if by strtod */
1.624 +#ifdef hardway
1.625 + if (width == 0 || width > sizeof (buf) - 1)
1.626 + width = sizeof (buf) - 1;
1.627 +#else
1.628 + /* size_t is unsigned, hence this optimisation */
1.629 + if (--width > sizeof (buf) - 2)
1.630 + width = sizeof (buf) - 2;
1.631 + width++;
1.632 +#endif
1.633 + flags |= SIGNOK | NDIGITS | DPTOK | EXPOK;
1.634 + for (p = buf; width; width--)
1.635 + {
1.636 + c = *fp->_p;
1.637 + /*
1.638 + * This code mimicks the integer conversion
1.639 + * code, but is much simpler.
1.640 + */
1.641 + switch (c)
1.642 + {
1.643 +
1.644 + case '0':
1.645 + case '1':
1.646 + case '2':
1.647 + case '3':
1.648 + case '4':
1.649 + case '5':
1.650 + case '6':
1.651 + case '7':
1.652 + case '8':
1.653 + case '9':
1.654 + flags &= ~(SIGNOK | NDIGITS);
1.655 + goto fok;
1.656 +
1.657 + case '+':
1.658 + case '-':
1.659 + if (flags & SIGNOK)
1.660 + {
1.661 + flags &= ~SIGNOK;
1.662 + goto fok;
1.663 + }
1.664 + break;
1.665 + case '.':
1.666 + if (flags & DPTOK)
1.667 + {
1.668 + flags &= ~(SIGNOK | DPTOK);
1.669 + goto fok;
1.670 + }
1.671 + break;
1.672 + case 'e':
1.673 + case 'E':
1.674 + /* no exponent without some digits */
1.675 + if ((flags & (NDIGITS | EXPOK)) == EXPOK)
1.676 + {
1.677 + flags =
1.678 + (flags & ~(EXPOK | DPTOK)) |
1.679 + SIGNOK | NDIGITS;
1.680 + goto fok;
1.681 + }
1.682 + break;
1.683 + }
1.684 + break;
1.685 + fok:
1.686 + *p++ = (char)c;
1.687 + if (--fp->_r > 0)
1.688 + fp->_p++;
1.689 + else
1.690 + if (__srefill (fp))
1.691 + break; /* EOF */
1.692 + }
1.693 + /*
1.694 + * If no digits, might be missing exponent digits
1.695 + * (just give back the exponent) or might be missing
1.696 + * regular digits, but had sign and/or decimal point.
1.697 + */
1.698 + if (flags & NDIGITS)
1.699 + {
1.700 + if (flags & EXPOK)
1.701 + {
1.702 + /* no digits at all */
1.703 + while (p > buf)
1.704 + ungetc (*(u_char *)-- p, fp);
1.705 + goto match_failure;
1.706 + }
1.707 + /* just a bad exponent (e and maybe sign) */
1.708 + c = *(u_char *)-- p;
1.709 + if (c != 'e' && c != 'E')
1.710 + {
1.711 + (void) ungetc (c, fp); /* sign */
1.712 + c = *(u_char *)-- p;
1.713 + }
1.714 + (void) ungetc (c, fp);
1.715 + }
1.716 + if ((flags & SUPPRESS) == 0)
1.717 + {
1.718 + double res;
1.719 +
1.720 + *p = 0;
1.721 + res = atof (buf);
1.722 + if (flags & LONG)
1.723 + {
1.724 + dp = va_arg (ap, double *);
1.725 + *dp = res;
1.726 + }
1.727 + else
1.728 + {
1.729 + flp = va_arg (ap, float *);
1.730 + *flp = (float)res;
1.731 + }
1.732 + nassigned++;
1.733 + }
1.734 + nread += p - buf;
1.735 + break;
1.736 + }
1.737 + }
1.738 +input_failure:
1.739 + return nassigned ? nassigned : -1;
1.740 +match_failure:
1.741 + return nassigned;
1.742 +}
1.743 +
1.744 +/*
1.745 + * Fill in the given table from the scanset at the given format
1.746 + * (just after `['). Return a pointer to the character past the
1.747 + * closing `]'. The table has a 1 wherever characters should be
1.748 + * considered part of the scanset.
1.749 + */
1.750 +
1.751 +/*static*/
1.752 +u_char *
1.753 +__sccl (register char *tab,register u_char *fmt)
1.754 +{
1.755 + register int c, n, v;
1.756 +
1.757 + /* first `clear' the whole table */
1.758 + c = *fmt++; /* first char hat => negated scanset */
1.759 + if (c == '^')
1.760 + {
1.761 + v = 1; /* default => accept */
1.762 + c = *fmt++; /* get new first char */
1.763 + }
1.764 + else
1.765 + v = 0; /* default => reject */
1.766 + /* should probably use memset here */
1.767 + for (n = 0; n < 256; n++)
1.768 + tab[n] = (char)v;
1.769 + if (c == 0)
1.770 + return fmt - 1; /* format ended before closing ] */
1.771 +
1.772 + /*
1.773 + * Now set the entries corresponding to the actual scanset to the
1.774 + * opposite of the above.
1.775 + *
1.776 + * The first character may be ']' (or '-') without being special; the
1.777 + * last character may be '-'.
1.778 + */
1.779 +
1.780 + v = 1 - v;
1.781 + for (;;)
1.782 + {
1.783 + tab[c] = (char)v; /* take character c */
1.784 + doswitch:
1.785 + n = *fmt++; /* and examine the next */
1.786 + switch (n)
1.787 + {
1.788 +
1.789 + case 0: /* format ended too soon */
1.790 + return fmt - 1;
1.791 +
1.792 + case '-':
1.793 + /*
1.794 + * A scanset of the form [01+-] is defined as `the digit 0, the
1.795 + * digit 1, the character +, the character -', but the effect of a
1.796 + * scanset such as [a-zA-Z0-9] is implementation defined. The V7
1.797 + * Unix scanf treats `a-z' as `the letters a through z', but treats
1.798 + * `a-a' as `the letter a, the character -, and the letter a'.
1.799 + *
1.800 + * For compatibility, the `-' is not considerd to define a range if
1.801 + * the character following it is either a close bracket (required by
1.802 + * ANSI) or is not numerically greater than the character we just
1.803 + * stored in the table (c).
1.804 + */
1.805 + n = *fmt;
1.806 + if (n == ']' || n < c)
1.807 + {
1.808 + c = '-';
1.809 + break; /* resume the for(;;) */
1.810 + }
1.811 + fmt++;
1.812 + do
1.813 + { /* fill in the range */
1.814 + tab[++c] = (char)v;
1.815 + }
1.816 + while (c < n);
1.817 +#if 1 /* XXX another disgusting compatibility hack */
1.818 + /*
1.819 + * Alas, the V7 Unix scanf also treats formats such
1.820 + * as [a-c-e] as `the letters a through e'. This too
1.821 + * is permitted by the standard....
1.822 + */
1.823 + goto doswitch;
1.824 +#else
1.825 + c = *fmt++;
1.826 + if (c == 0)
1.827 + return fmt - 1;
1.828 + if (c == ']')
1.829 + return fmt;
1.830 +
1.831 + break;
1.832 +#endif
1.833 +
1.834 + case ']': /* end of scanset */
1.835 + return fmt;
1.836 +
1.837 + default: /* just another character */
1.838 + c = n;
1.839 + break;
1.840 + }
1.841 + }
1.842 + /* NOTREACHED */
1.843 +}