📄 vfscanf.c
字号:
{ /* Add all the characters. */ for (cmpp = thousands; *cmpp != '\0'; ++cmpp) ADDW ((unsigned char) *cmpp); if (width > 0) width = avail; } else { /* The last read character is not part of the number anymore. */ ungetc (c, s); break; } }#endif } if (width > 0) --width; } while (width != 0 && inchar () != EOF); /* Have we read any character? If we try to read a number in hexadecimal notation and we have read only the `0x' prefix or no exponent this is an error. */ if (wpsize == 0 || (is_hexa && (wpsize == 2 || ! got_e))) conv_error (); scan_float: /* Convert the number. */ ADDW (L_('\0')); if (flags & LONGDBL) { long double d = __strtold_internal (wp, &tw, flags & GROUP); if (!(flags & SUPPRESS) && tw != wp) *ARG (long double *) = negative ? -d : d; } else if (flags & LONG) { double d = __strtod_internal (wp, &tw, flags & GROUP); if (!(flags & SUPPRESS) && tw != wp) *ARG (double *) = negative ? -d : d; } else { float d = __strtof_internal (wp, &tw, flags & GROUP); if (!(flags & SUPPRESS) && tw != wp) *ARG (float *) = negative ? -d : d; } if (tw == wp) conv_error (); if (!(flags & SUPPRESS)) ++done; break; case L_('['): /* Character class. */ if (flags & LONG) STRING_ARG (wstr, wchar_t); else STRING_ARG (str, char); if (*f == L_('^')) { ++f; not_in = 1; } else not_in = 0; if (width < 0) /* There is no width given so there is also no limit on the number of characters we read. Therefore we set width to a very high value to make the algorithm easier. */ width = INT_MAX;#ifdef COMPILE_WSCANF /* Find the beginning and the end of the scanlist. We are not creating a lookup table since it would have to be too large. Instead we search each time through the string. This is not a constant lookup time but who uses this feature deserves to be punished. */ tw = (wchar_t *) f; /* Marks the beginning. */ if (*f == L']') ++f; while ((fc = *f++) != L'\0' && fc != L']'); if (fc == L'\0') conv_error (); wp = (wchar_t *) f - 1;#else /* Fill WP with byte flags indexed by character. We will use this flag map for matching input characters. */ if (wpmax < UCHAR_MAX + 1) { wpmax = UCHAR_MAX + 1; wp = (char *) alloca (wpmax); } memset (wp, '\0', UCHAR_MAX + 1); fc = *f; if (fc == ']' || fc == '-') { /* If ] or - appears before any char in the set, it is not the terminator or separator, but the first char in the set. */ wp[fc] = 1; ++f; } while ((fc = *f++) != '\0' && fc != ']') if (fc == '-' && *f != '\0' && *f != ']' && (unsigned char) f[-2] <= (unsigned char) *f) { /* Add all characters from the one before the '-' up to (but not including) the next format char. */ for (fc = (unsigned char) f[-2]; fc < (unsigned char) *f; ++fc) wp[fc] = 1; } else /* Add the character to the flag map. */ wp[fc] = 1; if (fc == '\0') conv_error();#endif if (flags & LONG) { size_t now = read_in;#ifdef COMPILE_WSCANF if (inchar () == WEOF) input_error (); do { wchar_t *runp; /* Test whether it's in the scanlist. */ runp = tw; while (runp < wp) { if (runp[0] == L'-' && runp[1] != '\0' && runp + 1 != wp && runp != tw && (unsigned int) runp[-1] <= (unsigned int) runp[1]) { /* Match against all characters in between the first and last character of the sequence. */ wchar_t wc; for (wc = runp[-1] + 1; wc <= runp[1]; ++wc) if ((wint_t) wc == c) break; if (wc <= runp[1] && !not_in) break; if (wc <= runp[1] && not_in) { /* The current character is not in the scanset. */ ungetc (c, s); goto out; } runp += 2; } else { if ((wint_t) *runp == c && !not_in) break; if ((wint_t) *runp == c && not_in) { ungetc (c, s); goto out; } ++runp; } } if (runp == wp && !not_in) { ungetc (c, s); goto out; } if (!(flags & SUPPRESS)) { *wstr++ = c; if ((flags & MALLOC) && wstr == (wchar_t *) *strptr + strsize) { /* Enlarge the buffer. */ wstr = (wchar_t *) realloc (*strptr, (2 * strsize) * sizeof (wchar_t)); if (wstr == NULL) { /* Can't allocate that much. Last-ditch effort. */ wstr = (wchar_t *) realloc (*strptr, (strsize + 1) * sizeof (wchar_t)); if (wstr == NULL) { /* We lose. Oh well. Terminate the string and stop converting, so at least we don't skip any input. */ ((wchar_t *) (*strptr))[strsize - 1] = L'\0'; ++done; conv_error (); } else { *strptr = (char *) wstr; wstr += strsize; ++strsize; } } else { *strptr = (char *) wstr; wstr += strsize; strsize *= 2; } } } } while (--width > 0 && inchar () != WEOF); out:#else char buf[MB_LEN_MAX]; size_t cnt = 0; mbstate_t cstate; if (inchar () == EOF) input_error (); memset (&cstate, '\0', sizeof (cstate)); do { if (wp[c] == not_in) { ungetc_not_eof (c, s); break; } /* This is easy. */ if (!(flags & SUPPRESS)) { size_t n; /* Convert it into a wide character. */ buf[0] = c; n = __mbrtowc (wstr, buf, 1, &cstate); if (n == (size_t) -2) { /* Possibly correct character, just not enough input. */ ++cnt; assert (cnt < MB_CUR_MAX); continue; } cnt = 0; ++wstr; if ((flags & MALLOC) && wstr == (wchar_t *) *strptr + strsize) { /* Enlarge the buffer. */ wstr = (wchar_t *) realloc (*strptr, (2 * strsize * sizeof (wchar_t))); if (wstr == NULL) { /* Can't allocate that much. Last-ditch effort. */ wstr = (wchar_t *) realloc (*strptr, ((strsize + 1) * sizeof (wchar_t))); if (wstr == NULL) { /* We lose. Oh well. Terminate the string and stop converting, so at least we don't skip any input. */ ((wchar_t *) (*strptr))[strsize - 1] = L'\0'; ++done; conv_error (); } else { *strptr = (char *) wstr; wstr += strsize; ++strsize; } } else { *strptr = (char *) wstr; wstr += strsize; strsize *= 2; } } } if (--width <= 0) break; } while (inchar () != EOF); if (cnt != 0) /* We stopped in the middle of recognizing another character. That's a problem. */ encode_error ();#endif if (now == read_in) /* We haven't succesfully read any character. */ conv_error (); if (!(flags & SUPPRESS)) { *wstr++ = L'\0'; if ((flags & MALLOC) && wstr - (wchar_t *) *strptr != strsize) { wchar_t *cp = (wchar_t *) realloc (*strptr, ((wstr - (wchar_t *) *strptr) * sizeof(wchar_t))); if (cp != NULL) *strptr = (char *) cp; } ++done; } } else { size_t now = read_in; if (inchar () == EOF) input_error ();#ifdef COMPILE_WSCANF memset (&state, '\0', sizeof (state)); do { wchar_t *runp; size_t n; /* Test whether it's in the scanlist. */ runp = tw; while (runp < wp) { if (runp[0] == L'-' && runp[1] != '\0' && runp + 1 != wp && runp != tw && (unsigned int) runp[-1] <= (unsigned int) runp[1]) { /* Match against all characters in between the first and last character of the sequence. */ wchar_t wc; for (wc = runp[-1] + 1; wc <= runp[1]; ++wc) if ((wint_t) wc == c) break; if (wc <= runp[1] && !not_in) break; if (wc <= runp[1] && not_in) { /* The current character is not in the scanset. */ ungetc (c, s); goto out2; } runp += 2; } else { if ((wint_t) *runp == c && !not_in) break; if ((wint_t) *runp == c && not_in) { ungetc (c, s); goto out2; } ++runp; } } if (runp == wp && !not_in) { ungetc (c, s); goto out2; } if (!(flags & SUPPRESS)) { if ((flags & MALLOC) && str + MB_CUR_MAX >= *strptr + strsize) { /* Enlarge the buffer. */ size_t strleng = str - *strptr; char *newstr; newstr = (char *) realloc (*strptr, 2 * strsize); if (newstr == NULL) { /* Can't allocate that much. Last-ditch effort. */ newstr = (char *) realloc (*strptr, strleng + MB_CUR_MAX); if (newstr == NULL) { /* We lose. Oh well. Terminate the string and stop converting, so at least we don't skip any input. */ ((char *) (*strptr))[strleng] = '\0'; ++done; conv_error (); } else { *strptr = newstr; str = newstr + strleng; strsize = strleng + MB_CUR_MAX; } } else { *strptr = newstr; str = newstr + strleng; strsize *= 2; } } } n = __wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state); if (n == (size_t) -1) encode_error (); assert (n <= MB_CUR_MAX); str += n; } while (--width > 0 && inchar () != WEOF); out2:#else do { if (wp[c] == not_in) { ungetc_not_eof (c, s); break; } /* This is easy. */ if (!(flags & SUPPRESS)) { *str++ = c; if ((flags & MALLOC) && (char *) str == *strptr + strsize) { /* Enlarge the buffer. */ size_t newsize = 2 * strsize; allocagain: str = (char *) realloc (*strptr, newsize); if (str == NULL) { /* Can't allocate that much. Last-ditch effort. */ if (newsize > strsize + 1) { newsize = strsize + 1; goto allocagain; } /* We lose. Oh well. Terminate the string and stop converting, so at least we don't skip any input. */ ((char *) (*strptr))[strsize - 1] = '\0'; ++done; conv_error (); } else { *strptr = (char *) str; str += strsize; strsize = newsize; } } } } while (--width > 0 && inchar () != EOF);#endif if (now == read_in) /* We haven't succesfully read any character. */ conv_error (); if (!(flags & SUPPRESS)) {#ifdef COMPILE_WSCANF /* We have to emit the code to get into the initial state. */ char buf[MB_LEN_MAX]; size_t n = __wcrtomb (buf, L'\0', &state); if (n > 0 && (flags & MALLOC) && str + n >= *strptr + strsize) { /* Enlarge the buffer. */ size_t strleng = str - *strptr; char *newstr; newstr = (char *) realloc (*strptr, strleng + n + 1); if (newstr == NULL) { /* We lose. Oh well. Terminate the string and stop converting, so at least we don't skip any input. */ ((char *) (*strptr))[strleng] = '\0'; ++done; conv_error (); } else { *strptr = newstr; str = newstr + strleng; strsize = strleng + n + 1; } } str = __mempcpy (str, buf, n);#endif *str++ = '\0'; if ((flags & MALLOC) && str - *strptr != strsize) { char *cp = (char *) realloc (*strptr, str - *strptr); if (cp != NULL) *strptr = cp; } ++done; } } break; case L_('p'): /* Generic pointer. */ base = 16; /* A PTR must be the same size as a `long int'. */ flags &= ~(SHORT|LONGDBL); if (need_long) flags |= LONG; number_signed = 0; read_pointer = 1; goto number; default: /* If this is an unknown format character punt. */ conv_error (); } } /* The last thing we saw int the format string was a white space. Consume the last white spaces. */ if (skip_space) { do c = inchar (); while (ISSPACE (c)); ungetc (c, s); } errout: /* Unlock stream. */ UNLOCK_STREAM (s); if (errp != NULL) *errp |= errval; return done;}#ifdef COMPILE_WSCANFint__vfwscanf (FILE *s, const wchar_t *format, va_list argptr){ return _IO_vfwscanf (s, format, argptr, NULL);}#elseint__vfscanf (FILE *s, const char *format, va_list argptr){ return INTUSE(_IO_vfscanf) (s, format, argptr, NULL);}libc_hidden_def (__vfscanf)#endif#ifdef COMPILE_WSCANFweak_alias (__vfwscanf, vfwscanf)#elseweak_alias (__vfscanf, vfscanf)INTDEF(_IO_vfscanf)#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -