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

📄 vfscanf.c

📁 绝对正真的stdio.h的实现
💻 C
📖 第 1 页 / 共 4 页
字号:
	    }	  break;	case L_('c'):	/* Match characters.  */	  if ((flags & LONG) == 0)	    {	      if (!(flags & SUPPRESS))		{		  str = ARG (char *);		  if (str == NULL)		    conv_error ();		}	      c = inchar ();	      if (c == EOF)		input_error ();	      if (width == -1)		width = 1;#ifdef COMPILE_WSCANF	      /* We have to convert the wide character(s) into multibyte		 characters and store the result.  */	      memset (&state, '\0', sizeof (state));	      do		{		  size_t n;		  n = __wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state);		  if (n == (size_t) -1)		    /* No valid wide character.  */		    input_error ();		  /* Increment the output pointer.  Even if we don't		     write anything.  */		  str += n;		}	      while (--width > 0 && inchar () != EOF);#else	      if (!(flags & SUPPRESS))		{		  do		    *str++ = c;		  while (--width > 0 && inchar () != EOF);		}	      else		while (--width > 0 && inchar () != EOF);#endif	      if (!(flags & SUPPRESS))		++done;	      break;	    }	  /* FALLTHROUGH */	case L_('C'):	  if (!(flags & SUPPRESS))	    {	      wstr = ARG (wchar_t *);	      if (wstr == NULL)		conv_error ();	    }	  c = inchar ();	  if (c == EOF)	    input_error ();#ifdef COMPILE_WSCANF	  /* Just store the incoming wide characters.  */	  if (!(flags & SUPPRESS))	    {	      do		*wstr++ = c;	      while (--width > 0 && inchar () != EOF);	    }	  else	    while (--width > 0 && inchar () != EOF);#else	  {	    /* We have to convert the multibyte input sequence to wide	       characters.  */	    char buf[1];	    mbstate_t cstate;	    memset (&cstate, '\0', sizeof (cstate));	    do	      {		/* This is what we present the mbrtowc function first.  */		buf[0] = c;		while (1)		  {		    size_t n;		    n = __mbrtowc (!(flags & SUPPRESS) ? wstr : NULL,				   buf, 1, &cstate);		    if (n == (size_t) -2)		      {			/* Possibly correct character, just not enough			   input.  */			if (inchar () == EOF)			  encode_error ();			buf[0] = c;			continue;		      }		    if (n != 1)		      encode_error ();		    /* We have a match.  */		    break;		  }		/* Advance the result pointer.  */		++wstr;	      }	    while (--width > 0 && inchar () != EOF);	  }#endif	  if (!(flags & SUPPRESS))	    ++done;	  break;	case L_('s'):		/* Read a string.  */	  if (!(flags & LONG))	    {#define STRING_ARG(Str, Type)						      \	      do if (!(flags & SUPPRESS))				      \		{							      \		  if (flags & MALLOC)					      \		    {							      \		      /* The string is to be stored in a malloc'd buffer.  */ \		      strptr = ARG (char **);				      \		      if (strptr == NULL)				      \			conv_error ();					      \		      /* Allocate an initial buffer.  */		      \		      strsize = 100;					      \		      *strptr = (char *) malloc (strsize * sizeof (Type));    \		      Str = (Type *) *strptr;				      \		    }							      \		  else							      \		    Str = ARG (Type *);					      \		  if (Str == NULL)					      \		    conv_error ();					      \		} while (0)	      STRING_ARG (str, char);	      c = inchar ();	      if (c == EOF)		input_error ();#ifdef COMPILE_WSCANF	      memset (&state, '\0', sizeof (state));#endif	      do		{		  if (ISSPACE (c))		    {		      ungetc_not_eof (c, s);		      break;		    }#ifdef COMPILE_WSCANF		  /* This is quite complicated.  We have to convert the		     wide characters into multibyte characters and then		     store them.  */		  {		    size_t n;		    if (!(flags & SUPPRESS) && (flags & MALLOC)			&& str + MB_CUR_MAX >= *strptr + strsize)		      {			/* We have to enlarge the buffer if the `a' flag			   was given.  */			size_t strleng = str - *strptr;			char *newstr;			newstr = (char *) realloc (*strptr, strsize * 2);			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;		  }#else		  /* This is easy.  */		  if (!(flags & SUPPRESS))		    {		      *str++ = c;		      if ((flags & MALLOC)			  && (char *) str == *strptr + strsize)			{			  /* Enlarge the buffer.  */			  str = (char *) realloc (*strptr, 2 * strsize);			  if (str == NULL)			    {			      /* Can't allocate that much.  Last-ditch				 effort.  */			      str = (char *) realloc (*strptr, strsize + 1);			      if (str == NULL)				{				  /* 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;				}			    }			  else			    {			      *strptr = (char *) str;			      str += strsize;			      strsize *= 2;			    }			}		    }#endif		}	      while ((width <= 0 || --width > 0) && inchar () != EOF);	      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;	    }	  /* FALLTHROUGH */	case L_('S'):	  {#ifndef COMPILE_WSCANF	    mbstate_t cstate;#endif	    /* Wide character string.  */	    STRING_ARG (wstr, wchar_t);	    c = inchar ();	    if (c == EOF)	      input_error ();#ifndef COMPILE_WSCANF	    memset (&cstate, '\0', sizeof (cstate));#endif	    do	      {		if (ISSPACE (c))		  {		    ungetc_not_eof (c, s);		    break;		  }#ifdef COMPILE_WSCANF		/* This is easy.  */		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;			  }		      }		  }#else		{		  char buf[1];		  buf[0] = c;		  while (1)		    {		      size_t n;		      n = __mbrtowc (!(flags & SUPPRESS) ? wstr : NULL,				     buf, 1, &cstate);		      if (n == (size_t) -2)			{			  /* Possibly correct character, just not enough			     input.  */			  if (inchar () == EOF)			    encode_error ();			  buf[0] = c;			  continue;			}		      if (n != 1)			encode_error ();		      /* We have a match.  */		      ++wstr;		      break;		    }		  if (!(flags & SUPPRESS) && (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;			}		    }		}#endif	      }	    while ((width <= 0 || --width > 0) && inchar () != EOF);	    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;	      }	  }	  break;	case L_('x'):	/* Hexadecimal integer.  */	case L_('X'):	/* Ditto.  */	  base = 16;	  number_signed = 0;	  goto number;	case L_('o'):	/* Octal integer.  */	  base = 8;	  number_signed = 0;	  goto number;	case L_('u'):	/* Unsigned decimal integer.  */	  base = 10;	  number_signed = 0;	  goto number;	case L_('d'):	/* Signed decimal integer.  */	  base = 10;	  number_signed = 1;	  goto number;	case L_('i'):	/* Generic number.  */	  base = 0;	  number_signed = 1;	number:	  c = inchar ();	  if (c == EOF)	    input_error ();	  /* Check for a sign.  */	  if (c == L_('-') || c == L_('+'))	    {	      ADDW (c);	      if (width > 0)		--width;	      c = inchar ();	    }	  /* Look for a leading indication of base.  */	  if (width != 0 && c == L_('0'))	    {	      if (width > 0)		--width;	      ADDW (c);	      c = inchar ();	      if (width != 0 && TOLOWER (c) == L_('x'))		{		  if (base == 0)		    base = 16;		  if (base == 16)		    {		      if (width > 0)			--width;		      c = inchar ();		    }		}	      else if (base == 0)		base = 8;	    }	  if (base == 0)	    base = 10;	  if (base == 10 && (flags & I18N) != 0)	    {	      int from_level;	      int to_level;	      int level;#ifdef COMPILE_WSCANF	      const wchar_t *wcdigits[10];	      const wchar_t *wcdigits_extended[10];#else	      const char *mbdigits[10];	      const char *mbdigits_extended[10];#endif	      /*  "to_inpunct" is a map from ASCII digits to their		  equivalent in locale. This is defined for locales		  which use an extra digits set.  */	      wctrans_t map = __wctrans ("to_inpunct");	      int n;	      from_level = 0;#ifdef COMPILE_WSCANF	      to_level = _NL_CURRENT_WORD (LC_CTYPE,					   _NL_CTYPE_INDIGITS_WC_LEN) - 1;#else	      to_level = (uint32_t) curctype->values[_NL_ITEM_INDEX (_NL_CTYPE_INDIGITS_MB_LEN)].word - 1;#endif	      /* Get the alternative digit forms if there are any.  */	      if (__builtin_expect (map != NULL, 0))		{		  /*  Adding new level for extra digits set in locale file.  */		  ++to_level;		  for (n = 0; n < 10; ++n)		    {#ifdef COMPILE_WSCANF		      wcdigits[n] = (const wchar_t *)                        _NL_CURRENT (LC_CTYPE, _NL_CTYPE_INDIGITS0_WC + n);		      wchar_t *wc_extended = (wchar_t *)			alloca ((to_level + 2) * sizeof (wchar_t));		      __wmemcpy (wc_extended, wcdigits[n], to_level);		      wc_extended[to_level] = __towctrans (L'0' + n, map);		      wc_extended[to_level + 1] = '\0';		      wcdigits_extended[n] = wc_extended;#else		      mbdigits[n]                        = curctype->values[_NL_CTYPE_INDIGITS0_MB + n].string;		      /*  Get the equivalent wide char in map.  */		      wint_t extra_wcdigit = __towctrans (L'0' + n, map);		      /*  Convert it to multibyte representation.  */		      mbstate_t state;		      memset (&state, '\0', sizeof (state));		      char extra_mbdigit[MB_LEN_MAX];		      size_t mblen			= __wcrtomb (extra_mbdigit, extra_wcdigit, &state);		      if (mblen == (size_t) -1)			{			  /*  Ignore this new level.  */			  map = NULL;			  break;			}		      /*  Calculate the length of mbdigits[n].  */		      const char *last_char = mbdigits[n];		      for (level = 0; level < to_level; ++level)			last_char = strchr (last_char, '\0') + 1;		      size_t mbdigits_len = last_char - mbdigits[n];		      /*  Allocate memory for extended multibyte digit.  */		      char *mb_extended;		      mb_extended = (char *) alloca (mbdigits_len + mblen + 1);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -