📄 vfscanf.c
字号:
/* And get the mbdigits + extra_digit string. */ *(char *) __mempcpy (__mempcpy (mb_extended, mbdigits[n], mbdigits_len), extra_mbdigit, mblen) = '\0'; mbdigits_extended[n] = mb_extended;#endif } } /* Read the number into workspace. */ while (c != EOF && width != 0) { /* In this round we get the pointer to the digit strings and also perform the first round of comparisons. */ for (n = 0; n < 10; ++n) { /* Get the string for the digits with value N. */#ifdef COMPILE_WSCANF if (__builtin_expect (map != NULL, 0)) wcdigits[n] = wcdigits_extended[n]; else wcdigits[n] = (const wchar_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_INDIGITS0_WC + n); wcdigits[n] += from_level; if (c == (wint_t) *wcdigits[n]) { to_level = from_level; break; } /* Advance the pointer to the next string. */ ++wcdigits[n];#else const char *cmpp; int avail = width > 0 ? width : INT_MAX; if (__builtin_expect (map != NULL, 0)) mbdigits[n] = mbdigits_extended[n]; else mbdigits[n] = curctype->values[_NL_CTYPE_INDIGITS0_MB + n].string; for (level = 0; level < from_level; level++) mbdigits[n] = strchr (mbdigits[n], '\0') + 1; cmpp = mbdigits[n]; while ((unsigned char) *cmpp == c && avail > 0) { if (*++cmpp == '\0') break; else { if ((c = inchar ()) == EOF) break; --avail; } } if (*cmpp == '\0') { if (width > 0) width = avail; to_level = from_level; break; } /* We are pushing all read characters back. */ if (cmpp > mbdigits[n]) { ungetc (c, s); while (--cmpp > mbdigits[n]) ungetc_not_eof ((unsigned char) *cmpp, s); c = (unsigned char) *cmpp; } /* Advance the pointer to the next string. */ mbdigits[n] = strchr (mbdigits[n], '\0') + 1;#endif } if (n == 10) { /* Have not yet found the digit. */ for (level = from_level + 1; level <= to_level; ++level) { /* Search all ten digits of this level. */ for (n = 0; n < 10; ++n) {#ifdef COMPILE_WSCANF if (c == (wint_t) *wcdigits[n]) break; /* Advance the pointer to the next string. */ ++wcdigits[n];#else const char *cmpp; int avail = width > 0 ? width : INT_MAX; cmpp = mbdigits[n]; while ((unsigned char) *cmpp == c && avail > 0) { if (*++cmpp == '\0') break; else { if ((c = inchar ()) == EOF) break; --avail; } } if (*cmpp == '\0') { if (width > 0) width = avail; break; } /* We are pushing all read characters back. */ if (cmpp > mbdigits[n]) { ungetc (c, s); while (--cmpp > mbdigits[n]) ungetc_not_eof ((unsigned char) *cmpp, s); c = (unsigned char) *cmpp; } /* Advance the pointer to the next string. */ mbdigits[n] = strchr (mbdigits[n], '\0') + 1;#endif } if (n < 10) { /* Found it. */ from_level = level; to_level = level; break; } } } if (n < 10) c = L_('0') + n; else if ((flags & GROUP)#ifdef COMPILE_WSCANF && thousands != L'\0'#else && thousands != NULL#endif ) { /* Try matching against the thousands separator. */#ifdef COMPILE_WSCANF if (c != thousands) break;#else const char *cmpp = thousands; int avail = width > 0 ? width : INT_MAX; while ((unsigned char) *cmpp == c && avail > 0) { ADDW (c); if (*++cmpp == '\0') break; else { if ((c = inchar ()) == EOF) break; --avail; } } if (*cmpp != '\0') { /* We are pushing all read characters back. */ if (cmpp > thousands) { wpsize -= cmpp - thousands; ungetc (c, s); while (--cmpp > thousands) ungetc_not_eof ((unsigned char) *cmpp, s); c = (unsigned char) *cmpp; } break; } if (width > 0) width = avail; /* The last thousands character will be added back by the ADDW below. */ --wpsize;#endif } else break; ADDW (c); if (width > 0) --width; c = inchar (); } } else /* Read the number into workspace. */ while (c != EOF && width != 0) { if (base == 16) { if (!ISXDIGIT (c)) break; } else if (!ISDIGIT (c) || (int) (c - L_('0')) >= base) { if (base == 10 && (flags & GROUP)#ifdef COMPILE_WSCANF && thousands != L'\0'#else && thousands != NULL#endif ) { /* Try matching against the thousands separator. */#ifdef COMPILE_WSCANF if (c != thousands) break;#else const char *cmpp = thousands; int avail = width > 0 ? width : INT_MAX; while ((unsigned char) *cmpp == c && avail > 0) { ADDW (c); if (*++cmpp == '\0') break; else { if ((c = inchar ()) == EOF) break; --avail; } } if (*cmpp != '\0') { /* We are pushing all read characters back. */ if (cmpp > thousands) { wpsize -= cmpp - thousands; ungetc (c, s); while (--cmpp > thousands) ungetc_not_eof ((unsigned char) *cmpp, s); c = (unsigned char) *cmpp; } break; } if (width > 0) width = avail; /* The last thousands character will be added back by the ADDW below. */ --wpsize;#endif } else break; } ADDW (c); if (width > 0) --width; c = inchar (); } if (wpsize == 0 || (wpsize == 1 && (wp[0] == L_('+') || wp[0] == L_('-')))) { /* There was no number. If we are supposed to read a pointer we must recognize "(nil)" as well. */ if (wpsize == 0 && read_pointer && (width < 0 || width >= 0) && c == '(' && TOLOWER (inchar ()) == L_('n') && TOLOWER (inchar ()) == L_('i') && TOLOWER (inchar ()) == L_('l') && inchar () == L_(')')) /* We must produce the value of a NULL pointer. A single '0' digit is enough. */ ADDW (L_('0')); else { /* The last read character is not part of the number anymore. */ ungetc (c, s); conv_error (); } } else /* The just read character is not part of the number anymore. */ ungetc (c, s); /* Convert the number. */ ADDW (L_('\0')); if (need_longlong && (flags & LONGDBL)) { if (number_signed) num.q = __strtoll_internal (wp, &tw, base, flags & GROUP); else num.uq = __strtoull_internal (wp, &tw, base, flags & GROUP); } else { if (number_signed) num.l = __strtol_internal (wp, &tw, base, flags & GROUP); else num.ul = __strtoul_internal (wp, &tw, base, flags & GROUP); } if (wp == tw) conv_error (); if (!(flags & SUPPRESS)) { if (! number_signed) { if (need_longlong && (flags & LONGDBL)) *ARG (unsigned LONGLONG int *) = num.uq; else if (need_long && (flags & LONG)) *ARG (unsigned long int *) = num.ul; else if (flags & SHORT) *ARG (unsigned short int *) = (unsigned short int) num.ul; else if (!(flags & CHAR)) *ARG (unsigned int *) = (unsigned int) num.ul; else *ARG (unsigned char *) = (unsigned char) num.ul; } else { if (need_longlong && (flags & LONGDBL)) *ARG (LONGLONG int *) = num.q; else if (need_long && (flags & LONG)) *ARG (long int *) = num.l; else if (flags & SHORT) *ARG (short int *) = (short int) num.l; else if (!(flags & CHAR)) *ARG (int *) = (int) num.l; else *ARG (signed char *) = (signed char) num.ul; } ++done; } break; case L_('e'): /* Floating-point numbers. */ case L_('E'): case L_('f'): case L_('F'): case L_('g'): case L_('G'): case L_('a'): case L_('A'): c = inchar (); if (c == EOF) input_error (); /* Check for a sign. */ if (c == L_('-') || c == L_('+')) { negative = c == L_('-'); if (width == 0 || inchar () == EOF) /* EOF is only an input error before we read any chars. */ conv_error (); if (! ISDIGIT (c) && TOLOWER (c) != L_('i') && TOLOWER (c) != L_('n')) {#ifdef COMPILE_WSCANF if (c != decimal) { /* This is no valid number. */ ungetc (c, s); conv_error (); }#else /* Match against the decimal point. At this point we are taking advantage of the fact that we can push more than one character back. This is (almost) never necessary since the decimal point string hopefully never contains more than one byte. */ const char *cmpp = decimal; int avail = width > 0 ? width : INT_MAX; while ((unsigned char) *cmpp == c && avail > 0) if (*++cmpp == '\0') break; else { if (inchar () == EOF) break; --avail; } if (*cmpp != '\0') { /* This is no valid number. */ while (1) { ungetc (c, s); if (cmpp == decimal) break; c = (unsigned char) *--cmpp; } conv_error (); } if (width > 0) width = avail;#endif } if (width > 0) --width; } else negative = 0; /* Take care for the special arguments "nan" and "inf". */ if (TOLOWER (c) == L_('n')) { /* Maybe "nan". */ ADDW (c); if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('a')) conv_error (); if (width > 0) --width; ADDW (c); if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('n')) conv_error (); if (width > 0) --width; ADDW (c); /* It is "nan". */ goto scan_float; } else if (TOLOWER (c) == L_('i')) { /* Maybe "inf" or "infinity". */ ADDW (c); if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('n')) conv_error (); if (width > 0) --width; ADDW (c); if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('f')) conv_error (); if (width > 0) --width; ADDW (c); /* It is as least "inf". */ if (width != 0 && inchar () != EOF) { if (TOLOWER (c) == L_('i')) { if (width > 0) --width; /* Now we have to read the rest as well. */ ADDW (c); if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('n')) conv_error (); if (width > 0) --width; ADDW (c); if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('i')) conv_error (); if (width > 0) --width; ADDW (c); if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('t')) conv_error (); if (width > 0) --width; ADDW (c); if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('y')) conv_error (); if (width > 0) --width; ADDW (c); } else /* Never mind. */ ungetc (c, s); } goto scan_float; } is_hexa = 0; exp_char = L_('e'); if (width != 0 && c == L_('0')) { ADDW (c); c = inchar (); if (width > 0) --width; if (width != 0 && TOLOWER (c) == L_('x')) { /* It is a number in hexadecimal format. */ ADDW (c); is_hexa = 1; exp_char = L_('p'); /* Grouping is not allowed. */ flags &= ~GROUP; c = inchar (); if (width > 0) --width; } } got_dot = got_e = 0; do { if (ISDIGIT (c)) ADDW (c); else if (!got_e && is_hexa && ISXDIGIT (c)) ADDW (c); else if (got_e && wp[wpsize - 1] == exp_char && (c == L_('-') || c == L_('+'))) ADDW (c); else if (wpsize > 0 && !got_e && (CHAR_T) TOLOWER (c) == exp_char) { ADDW (exp_char); got_e = got_dot = 1; } else {#ifdef COMPILE_WSCANF if (! got_dot && c == decimal) { ADDW (c); got_dot = 1; } else if ((flags & GROUP) != 0 && thousands != L'\0' && ! got_dot && c == thousands) ADDW (c); else { /* The last read character is not part of the number anymore. */ ungetc (c, s); break; }#else const char *cmpp = decimal; int avail = width > 0 ? width : INT_MAX; if (! got_dot) { while ((unsigned char) *cmpp == c && avail > 0) if (*++cmpp == '\0') break; else { if (inchar () == EOF) break; --avail; } } if (*cmpp == '\0') { /* Add all the characters. */ for (cmpp = decimal; *cmpp != '\0'; ++cmpp) ADDW ((unsigned char) *cmpp); if (width > 0) width = avail; got_dot = 1; } else { /* Figure out whether it is a thousands separator. There is one problem: we possibly read more than one character. We cannot push them back but since we know that parts of the `decimal' string matched, we can compare against it. */ const char *cmp2p = thousands; if ((flags & GROUP) != 0 && thousands != NULL && ! got_dot) { while (cmp2p - thousands < cmpp - decimal && *cmp2p == decimal[cmp2p - thousands]) ++cmp2p; if (cmp2p - thousands == cmpp - decimal) { while ((unsigned char) *cmp2p == c && avail > 0) if (*++cmp2p == '\0') break; else { if (inchar () == EOF) break; --avail; } } } if (cmp2p != NULL && *cmp2p == '\0')
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -