📄 vfscanf.c
字号:
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: /* scan an integer as if by strtol/strtoul */#ifdef hardway if (width == 0 || width > sizeof (buf) - 1) width = sizeof (buf) - 1;#else /* size_t is unsigned, hence this optimisation */ if (--width > sizeof (buf) - 2) width = sizeof (buf) - 2; width++;#endif flags |= SIGNOK | NDIGITS | NZDIGITS; for (p = buf; width; 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 (base == 0) { base = 8; flags |= PFXOK; } if (flags & NZDIGITS) flags &= ~(SIGNOK | NZDIGITS | NDIGITS); else flags &= ~(SIGNOK | PFXOK | NDIGITS); goto ok; /* 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); 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); 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); 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; 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; 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) (buf, (char **) NULL, base); if (flags & POINTER) *(va_arg (ap, _PTR *)) = (_PTR) res; else if (flags & SHORT) { sp = va_arg (ap, short *); *sp = res; } else if (flags & LONG) { lp = va_arg (ap, long *); *lp = res; } else { ip = va_arg (ap, int *); *ip = res; } nassigned++; } nread += p - buf; break;#ifdef FLOATING_POINT case CT_FLOAT: /* scan a floating point number as if by strtod */#ifdef hardway if (width == 0 || width > sizeof (buf) - 1) width = sizeof (buf) - 1;#else /* size_t is unsigned, hence this optimisation */ if (--width > sizeof (buf) - 2) width = sizeof (buf) - 2; width++;#endif flags |= SIGNOK | NDIGITS | DPTOK | EXPOK; for (p = buf; width; width--) { c = *fp->_p; /* * This code mimicks the integer conversion * code, but is much simpler. */ switch (c) { case '0': 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); goto fok; } break; case 'e': case 'E': /* no exponent without some digits */ if ((flags & (NDIGITS | EXPOK)) == EXPOK) { flags = (flags & ~(EXPOK | DPTOK)) | SIGNOK | NDIGITS; goto fok; } break; } break; fok: *p++ = c; if (--fp->_r > 0) fp->_p++; else#ifndef CYGNUS_NEC if (__srefill (fp))#endif break; /* EOF */ } /* * 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); goto match_failure; } /* just a bad exponent (e and maybe sign) */ c = *(u_char *)-- p; if (c != 'e' && c != 'E') { _CAST_VOID ungetc (c, fp); /* sign */ c = *(u_char *)-- p; } _CAST_VOID ungetc (c, fp); } if ((flags & SUPPRESS) == 0) { double res; *p = 0; res = atof (buf); if (flags & LONG) { dp = va_arg (ap, double *); *dp = res; } else if (flags & LONGDBL) { ldp = va_arg (ap, _LONG_DOUBLE *); *ldp = res; } else { flp = va_arg (ap, float *); *flp = res; } nassigned++; } nread += p - buf; break;#endif /* FLOATING_POINT */ } }input_failure: return nassigned ? nassigned : -1;match_failure: return nassigned;}/* * Fill in the given table from the scanset at the given format * (just after `['). Return a pointer to the character past the * closing `]'. The table has a 1 wherever characters should be * considered part of the scanset. *//*static*/u_char *__sccl (tab, fmt) register char *tab; register u_char *fmt;{ register int c, n, v; /* first `clear' the whole table */ c = *fmt++; /* first char hat => negated scanset */ if (c == '^') { v = 1; /* default => accept */ c = *fmt++; /* get new first char */ } else v = 0; /* default => reject */ /* should probably use memset here */ for (n = 0; n < 256; n++) tab[n] = v; if (c == 0) return fmt - 1; /* format ended before closing ] */ /* * Now set the entries corresponding to the actual scanset to the * opposite of the above. * * The first character may be ']' (or '-') without being special; the * last character may be '-'. */ v = 1 - v; for (;;) { tab[c] = v; /* take character c */ doswitch: n = *fmt++; /* and examine the next */ switch (n) { case 0: /* format ended too soon */ return fmt - 1; case '-': /* * A scanset of the form [01+-] is defined as `the digit 0, the * digit 1, the character +, the character -', but the effect of a * scanset such as [a-zA-Z0-9] is implementation defined. The V7 * Unix scanf treats `a-z' as `the letters a through z', but treats * `a-a' as `the letter a, the character -, and the letter a'. * * For compatibility, the `-' is not considerd to define a range if * the character following it is either a close bracket (required by * ANSI) or is not numerically greater than the character we just * stored in the table (c). */ n = *fmt; if (n == ']' || n < c) { c = '-'; break; /* resume the for(;;) */ } fmt++; do { /* fill in the range */ tab[++c] = v; } while (c < n);#if 1 /* XXX another disgusting compatibility hack */ /* * Alas, the V7 Unix scanf also treats formats such * as [a-c-e] as `the letters a through e'. This too * is permitted by the standard.... */ goto doswitch;#else c = *fmt++; if (c == 0) return fmt - 1; if (c == ']') return fmt;#endif break; case ']': /* end of scanset */ return fmt; default: /* just another character */ c = n; break; } } /* NOTREACHED */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -