⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vfscanf.c

📁 绝对正真的stdio.h的实现
💻 C
📖 第 1 页 / 共 4 页
字号:
		      /*  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 + -