📄 vfscanf.c
字号:
if (__srefill (fp))#endif goto input_failure; } } } else /* save to counter-act changes made to flags when processing */ orig_flags = flags; /* * Do the conversion. */ switch (type) { case CT_CHAR: /* scan arbitrary characters (sets NOSKIP) */ if (width == 0) width = 1; if (flags & SUPPRESS) { size_t sum = 0; for (;;) { if ((n = fp->_r) < (int)width) { sum += n; width -= n; fp->_p += n;#ifndef CYGNUS_NEC if (__srefill (fp)) {#endif if (sum == 0) goto input_failure; break;#ifndef CYGNUS_NEC }#endif } else { sum += width; fp->_r -= width; fp->_p += width; break; } } nread += sum; } else { int n = width; if (!looped) { if (flags & VECTOR) ch_dest = vec_buf.c; else ch_dest = va_arg (ap, char *); }#ifdef CYGNUS_NEC /* Kludge city for the moment */ if (fp->_r == 0) goto input_failure; while (n && fp->_r) { *ch_dest++ = *(fp->_p++); n--; fp->_r--; nread++; }#else size_t r = fread (ch_dest, 1, width, fp); if (r == 0) goto input_failure; nread += r; ch_dest += r;#endif if (!(flags & VECTOR)) nassigned++; } break; case CT_CCL: /* scan a (nonempty) character class (sets NOSKIP) */ if (width == 0) width = ~0; /* `infinity' */ /* take only those things in the class */ if (flags & SUPPRESS) { n = 0; while (ccltab[*fp->_p]) { n++, fp->_r--, fp->_p++; if (--width == 0) break; if (BufferEmpty) { if (n == 0) goto input_failure; break; } } if (n == 0) goto match_failure; } else { p0 = p = va_arg (ap, char *); while (ccltab[*fp->_p]) { fp->_r--; *p++ = *fp->_p++; if (--width == 0) break; if (BufferEmpty) { if (p == p0) goto input_failure; break; } } n = p - p0; if (n == 0) goto match_failure; *p = 0; nassigned++; } nread += n; break; case CT_STRING: /* like CCL, but zero-length string OK, & no NOSKIP */ if (width == 0) width = ~0; if (flags & SUPPRESS) { n = 0; while (!isspace (*fp->_p)) { n++, fp->_r--, fp->_p++; if (--width == 0) break; if (BufferEmpty) break; } nread += n; } else { p0 = p = va_arg (ap, char *); while (!isspace (*fp->_p)) { fp->_r--; *p++ = *fp->_p++; if (--width == 0) break; if (BufferEmpty) break; } *p = 0; nread += p - p0; nassigned++; } continue; case CT_INT: { unsigned int_width_left = 0; int skips = 0; int_width = width;#ifdef hardway if (int_width == 0 || int_width > sizeof (buf) - 1)#else /* size_t is unsigned, hence this optimisation */ if (int_width - 1 > sizeof (buf) - 2)#endif { int_width_left = width - (sizeof (buf) - 1); int_width = sizeof (buf) - 1; } flags |= SIGNOK | NDIGITS | NZDIGITS | NNZDIGITS; for (p = buf; int_width; int_width--) { c = *fp->_p; /* * Switch on the character; `goto ok' if we * accept it as a part of number. */ switch (c) { /* * The digit 0 is always legal, but is special. * For %i conversions, if no digits (zero or nonzero) * have been scanned (only signs), we will have base==0. * In that case, we should set it to 8 and enable 0x * prefixing. Also, if we have not scanned zero digits * before this, do not turn off prefixing (someone else * will turn it off if we have scanned any nonzero digits). */ case '0': if (! (flags & NNZDIGITS)) goto ok; if (base == 0) { base = 8; flags |= PFXOK; } if (flags & NZDIGITS) { flags &= ~(SIGNOK | NZDIGITS | NDIGITS); goto ok; } flags &= ~(SIGNOK | PFXOK | NDIGITS); if (int_width_left) { int_width_left--; int_width++; } ++skips; goto skip; /* 1 through 7 always legal */ case '1': case '2': case '3': case '4': case '5': case '6': case '7': base = basefix[base]; flags &= ~(SIGNOK | PFXOK | NDIGITS | NNZDIGITS); goto ok; /* digits 8 and 9 ok iff decimal or hex */ case '8': case '9': base = basefix[base]; if (base <= 8) break; /* not legal here */ flags &= ~(SIGNOK | PFXOK | NDIGITS | NNZDIGITS); goto ok; /* letters ok iff hex */ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': /* no need to fix base here */ if (base <= 10) break; /* not legal here */ flags &= ~(SIGNOK | PFXOK | NDIGITS | NNZDIGITS); goto ok; /* sign ok only as first character */ case '+': case '-': if (flags & SIGNOK) { flags &= ~SIGNOK; goto ok; } break; /* x ok iff flag still set & 2nd char */ case 'x': case 'X': if (flags & PFXOK && p == buf + 1) { base = 16;/* if %i */ flags &= ~PFXOK; /* We must reset the NZDIGITS and NDIGITS flags that would have been unset by seeing the zero that preceded the X or x. */ flags |= NZDIGITS | NDIGITS; goto ok; } break; } /* * If we got here, c is not a legal character * for a number. Stop accumulating digits. */ break; ok: /* * c is legal: store it and look at the next. */ *p++ = c; skip: if (--fp->_r > 0) fp->_p++; else#ifndef CYGNUS_NEC if (__srefill (fp))#endif break; /* EOF */ } /* * If we had only a sign, it is no good; push back the sign. * If the number ends in `x', it was [sign] '0' 'x', so push back * the x and treat it as [sign] '0'. */ if (flags & NDIGITS) { if (p > buf) _CAST_VOID ungetc (*(u_char *)-- p, fp); goto match_failure; } c = ((u_char *) p)[-1]; if (c == 'x' || c == 'X') { --p; /*(void)*/ ungetc (c, fp); } if ((flags & SUPPRESS) == 0) { u_long res; *p = 0; res = (*ccfn) (rptr, buf, (char **) NULL, base); if ((flags & POINTER) && !(flags & VECTOR)) *(va_arg (ap, _PTR *)) = (_PTR) (unsigned _POINTER_INT) res; else if (flags & SHORT) { if (!(flags & VECTOR)) sp = va_arg (ap, short *); else if (!looped) sp = vec_buf.h; *sp++ = res; } else if (flags & LONG) { if (!(flags & VECTOR)) lp = va_arg (ap, long *); else if (!looped) lp = vec_buf.l; *lp++ = res; }#ifndef _NO_LONGLONG else if (flags & LONGDBL) { u_long_long resll; if (ccfn == _strtoul_r) resll = _strtoull_r (rptr, buf, (char **) NULL, base); else resll = _strtoll_r (rptr, buf, (char **) NULL, base); llp = va_arg (ap, long long*); *llp = resll; }#endif else { if (!(flags & VECTOR)) { ip = va_arg (ap, int *); *ip++ = res; } else { if (!looped) ch_dest = vec_buf.c; *ch_dest++ = (char)res; } } if (!(flags & VECTOR)) nassigned++; } nread += p - buf + skips; break; }#ifdef FLOATING_POINT case CT_FLOAT: { /* scan a floating point number as if by strtod */ /* This code used to assume that the number of digits is reasonable. However, ANSI / ISO C makes no such stipulation; we have to get exact results even when there is an unreasonable amount of leading zeroes. */ long leading_zeroes = 0; long zeroes, exp_adjust; char *exp_start = NULL; unsigned fl_width = width; unsigned width_left = 0;#ifdef hardway if (fl_width == 0 || fl_width > sizeof (buf) - 1)#else /* size_t is unsigned, hence this optimisation */ if (fl_width - 1 > sizeof (buf) - 2)#endif { width_left = fl_width - (sizeof (buf) - 1); fl_width = sizeof (buf) - 1; } flags |= SIGNOK | NDIGITS | DPTOK | EXPOK; zeroes = 0; exp_adjust = 0; for (p = buf; fl_width; ) { c = *fp->_p; /* * This code mimicks the integer conversion * code, but is much simpler. */ switch (c) { case '0': if (flags & NDIGITS) { flags &= ~SIGNOK; zeroes++; if (width_left) { width_left--; fl_width++; } goto fskip; } /* Fall through. */ case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': flags &= ~(SIGNOK | NDIGITS); goto fok; case '+': case '-': if (flags & SIGNOK) { flags &= ~SIGNOK; goto fok; } break; case '.': if (flags & DPTOK) { flags &= ~(SIGNOK | DPTOK); leading_zeroes = zeroes; goto fok; } break; case 'e': case 'E': /* no exponent without some digits */ if ((flags & (NDIGITS | EXPOK)) == EXPOK || ((flags & EXPOK) && zeroes)) { if (! (flags & DPTOK)) { exp_adjust = zeroes - leading_zeroes; exp_start = p; } flags = (flags & ~(EXPOK | DPTOK)) | SIGNOK | NDIGITS; zeroes = 0; goto fok; } break; } break; fok: *p++ = c; fskip: fl_width--; ++nread; if (--fp->_r > 0) fp->_p++; else#ifndef CYGNUS_NEC if (__srefill (fp))#endif break; /* EOF */ } if (zeroes) flags &= ~NDIGITS; /* * If no digits, might be missing exponent digits * (just give back the exponent) or might be missing * regular digits, but had sign and/or decimal point. */ if (flags & NDIGITS) { if (flags & EXPOK) { /* no digits at all */ while (p > buf) { ungetc (*(u_char *)-- p, fp); --nread; } goto match_failure; } /* just a bad exponent (e and maybe sign) */ c = *(u_char *)-- p; --nread; if (c != 'e' && c != 'E') { _CAST_VOID ungetc (c, fp); /* sign */ c = *(u_char *)-- p; --nread; } _CAST_VOID ungetc (c, fp); } if ((flags & SUPPRESS) == 0) {#ifdef _NO_LONGDBL double res;#else /* !_NO_LONG_DBL */ long double res;#endif /* !_NO_LONG_DBL */ long new_exp = 0; *p = 0; if ((flags & (DPTOK | EXPOK)) == EXPOK) { exp_adjust = zeroes - leading_zeroes; new_exp = -exp_adjust; exp_start = p; } else if (exp_adjust) new_exp = _strtol_r (rptr, (exp_start + 1), NULL, 10) - exp_adjust; if (exp_adjust) { /* If there might not be enough space for the new exponent, truncate some trailing digits to make room. */ if (exp_start >= buf + sizeof (buf) - MAX_LONG_LEN) exp_start = buf + sizeof (buf) - MAX_LONG_LEN - 1; sprintf (exp_start, "e%ld", new_exp); }#ifdef __SPE__ if (flags & FIXEDPOINT) { __uint64_t ufix64; if (flags & SIGNED) ufix64 = (__uint64_t)_strtosfix64_r (rptr, buf, NULL); else ufix64 = _strtoufix64_r (rptr, buf, NULL); if (flags & SHORT) { __uint16_t *sp = va_arg (ap, __uint16_t *); *sp = (__uint16_t)(ufix64 >> 48); } else if (flags & LONG) { __uint64_t *llp = va_arg (ap, __uint64_t *); *llp = ufix64; } else { __uint32_t *lp = va_arg (ap, __uint32_t *); *lp = (__uint32_t)(ufix64 >> 32); } nassigned++; break; } #endif /* __SPE__ */#ifdef _NO_LONGDBL res = _strtod_r (rptr, buf, NULL);#else /* !_NO_LONGDBL */ res = _strtold (buf, NULL);#endif /* !_NO_LONGDBL */ if (flags & LONG) { dp = va_arg (ap, double *); *dp = res; } else if (flags & LONGDBL) { ldp = va_arg (ap, _LONG_DOUBLE *); *ldp = res; } else { if (!(flags & VECTOR)) flp = va_arg (ap, float *); else if (!looped) flp = vec_buf.f; *flp++ = res; } if (!(flags & VECTOR)) nassigned++; } break; }#endif /* FLOATING_POINT */ } if (vec_read_count-- > 1) { looped = 1; goto process; } if (flags & VECTOR) { int i; unsigned long *vp = va_arg (ap, unsigned long *); for (i = 0; i < 4; ++i) *vp++ = vec_buf.l[i]; nassigned++; } }input_failure: return nassigned ? nassigned : -1;match_failure: return nassigned;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -