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

📄 vfscanf.c

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