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

📄 vfscanf.c

📁 Newlib 嵌入式 C库 标准实现代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		case 'B':		case 'C':		case 'D':		case 'E':		case 'F':		case 'a':		case 'b':		case 'c':		case 'd':		case 'e':		case 'f':		  /* no need to fix base here */		  if (base <= 10)		    break;	/* not legal here */		  flags &= ~(SIGNOK | PFXOK | NDIGITS | NNZDIGITS);		  goto ok;		  /* sign ok only as first character */		case '+':		case '-':		  if (flags & SIGNOK)		    {		      flags &= ~SIGNOK;		      goto ok;		    }		  break;		  /* x ok iff flag still set & single 0 seen */		case 'x':		case 'X':		  if ((flags & (PFXOK | NZDIGITS)) == PFXOK)		    {		      base = 16;/* if %i */		      flags &= ~PFXOK;		      /* We must reset the NZDIGITS and NDIGITS			 flags that would have been unset by seeing			 the zero that preceded the X or x.  */		      flags |= NZDIGITS | NDIGITS;		      goto ok;		    }		  break;		}	      /*	       * If we got here, c is not a legal character	       * for a number.  Stop accumulating digits.	       */	      break;	    ok:	      /*	       * c is legal: store it and look at the next.	       */	      *p++ = c;	    skip:	      if (--fp->_r > 0)		fp->_p++;	      else	      if (__srefill_r (rptr, fp))		break;		/* EOF */	    }	  /*	   * If we had only a sign, it is no good; push back the sign.	   * If the number ends in `x', it was [sign] '0' 'x', so push back	   * the x and treat it as [sign] '0'.	   * Use of ungetc here and below assumes ASCII encoding; we are only	   * pushing back 7-bit characters, so casting to unsigned char is	   * not necessary.	   */	  if (flags & NDIGITS)	    {	      if (p > buf)		_ungetc_r (rptr, *--p, fp); /* [-+xX] */	      if (p == buf)		goto match_failure;	    }	  if ((flags & SUPPRESS) == 0)	    {	      u_long res;	      *p = 0;	      res = (*ccfn) (rptr, buf, (char **) NULL, base);	      if (flags & POINTER)		{		  void **vp = GET_ARG (N, ap, void **);#ifndef _NO_LONGLONG		  if (sizeof (uintptr_t) > sizeof (u_long))		    {		      u_long_long resll;		      resll = _strtoull_r (rptr, buf, (char **) NULL, base);		      *vp = (void *) (uintptr_t) resll;		    }		  else#endif /* !_NO_LONGLONG */		    *vp = (void *) (uintptr_t) res;		}#ifdef _WANT_IO_C99_FORMATS	      else if (flags & CHAR)		{		  cp = GET_ARG (N, ap, char *);		  *cp = res;		}#endif	      else if (flags & SHORT)		{		  sp = GET_ARG (N, ap, short *);		  *sp = res;		}	      else if (flags & LONG)		{		  lp = GET_ARG (N, ap, long *);		  *lp = res;		}#ifndef _NO_LONGLONG	      else if (flags & LONGDBL)		{		  u_long_long resll;		  if (ccfn == _strtoul_r)		    resll = _strtoull_r (rptr, buf, (char **) NULL, base);		  else		    resll = _strtoll_r (rptr, buf, (char **) NULL, base);		  llp = GET_ARG (N, ap, long long*);		  *llp = resll;		}#endif	      else		{		  ip = GET_ARG (N, ap, int *);		  *ip = res;		}	      nassigned++;	    }	  nread += p - buf + skips;	  break;	}#ifdef FLOATING_POINT	case CT_FLOAT:	{	  /* scan a floating point number as if by strtod */	  /* This code used to assume that the number of digits is reasonable.	     However, ANSI / ISO C makes no such stipulation; we have to get	     exact results even when there is an unreasonable amount of	     leading zeroes.  */	  long leading_zeroes = 0;	  long zeroes, exp_adjust;	  char *exp_start = NULL;	  unsigned width_left = 0;	  char nancount = 0;	  char infcount = 0;#ifdef hardway	  if (width == 0 || width > sizeof (buf) - 1)#else	  /* size_t is unsigned, hence this optimisation */	  if (width - 1 > sizeof (buf) - 2)#endif	    {	      width_left = width - (sizeof (buf) - 1);	      width = sizeof (buf) - 1;	    }	  flags |= SIGNOK | NDIGITS | DPTOK | EXPOK;	  zeroes = 0;	  exp_adjust = 0;	  for (p = buf; width; )	    {	      c = *fp->_p;	      /*	       * This code mimicks the integer conversion	       * code, but is much simpler.	       */	      switch (c)		{		case '0':		  if (flags & NDIGITS)		    {		      flags &= ~SIGNOK;		      zeroes++;		      if (width_left)			{			  width_left--;			  width++;			}		      goto fskip;		    }		  /* Fall through.  */		case '1':		case '2':		case '3':		case '4':		case '5':		case '6':		case '7':		case '8':		case '9':		  if (nancount + infcount == 0)		    {		      flags &= ~(SIGNOK | NDIGITS);		      goto fok;		    }		  break;		case '+':		case '-':		  if (flags & SIGNOK)		    {		      flags &= ~SIGNOK;		      goto fok;		    }		  break;		case 'n':		case 'N':		  if (nancount == 0		      && (flags & (NDIGITS | DPTOK | EXPOK)) ==				  (NDIGITS | DPTOK | EXPOK))		    {		      flags &= ~(SIGNOK | DPTOK | EXPOK | NDIGITS);		      nancount = 1;		      goto fok;		    }		  if (nancount == 2)		    {		      nancount = 3;		      goto fok;		    }		  if (infcount == 1 || infcount == 4)		    {		      infcount++;		      goto fok;		    }		  break;		case 'a':		case 'A':		  if (nancount == 1)		    {		      nancount = 2;		      goto fok;		    }		  break;		case 'i':		case 'I':		  if (infcount == 0		      && (flags & (NDIGITS | DPTOK | EXPOK)) ==				  (NDIGITS | DPTOK | EXPOK))		    {		      flags &= ~(SIGNOK | DPTOK | EXPOK | NDIGITS);		      infcount = 1;		      goto fok;		    }		  if (infcount == 3 || infcount == 5)		    {		      infcount++;		      goto fok;		    }		  break;		case 'f':		case 'F':		  if (infcount == 2)		    {		      infcount = 3;		      goto fok;		    }		  break;		case 't':		case 'T':		  if (infcount == 6)		    {		      infcount = 7;		      goto fok;		    }		  break;		case 'y':		case 'Y':		  if (infcount == 7)		    {		      infcount = 8;		      goto fok;		    }		  break;		case '.':		  if (flags & DPTOK)		    {		      flags &= ~(SIGNOK | DPTOK);		      leading_zeroes = zeroes;		      goto fok;		    }		  break;		case 'e':		case 'E':		  /* no exponent without some digits */		  if ((flags & (NDIGITS | EXPOK)) == EXPOK		      || ((flags & EXPOK) && zeroes))		    {		      if (! (flags & DPTOK))			{			  exp_adjust = zeroes - leading_zeroes;			  exp_start = p;			}		      flags =			(flags & ~(EXPOK | DPTOK)) |			SIGNOK | NDIGITS;		      zeroes = 0;		      goto fok;		    }		  break;		}	      break;	    fok:	      *p++ = c;	    fskip:	      width--;	      ++nread;	      if (--fp->_r > 0)		fp->_p++;	      else	      if (__srefill_r (rptr, fp))		break;		/* EOF */	    }	  if (zeroes)	    flags &= ~NDIGITS;	  /* We may have a 'N' or possibly even [sign] 'N' 'a' as the	     start of 'NaN', only to run out of chars before it was	     complete (or having encountered a non-matching char).  So	     check here if we have an outstanding nancount, and if so	     put back the chars we did swallow and treat as a failed	     match.	     FIXME - we still don't handle NAN([0xdigits]).  */	  if (nancount - 1U < 2U) /* nancount && nancount < 3 */	    {	      /* Newlib's ungetc works even if we called __srefill in		 the middle of a partial parse, but POSIX does not		 guarantee that in all implementations of ungetc.  */	      while (p > buf)		{		  _ungetc_r (rptr, *--p, fp); /* [-+nNaA] */		  --nread;		}	      goto match_failure;	    }	  /* Likewise for 'inf' and 'infinity'.	 But be careful that	     'infinite' consumes only 3 characters, leaving the stream	     at the second 'i'.	 */	  if (infcount - 1U < 7U) /* infcount && infcount < 8 */	    {	      if (infcount >= 3) /* valid 'inf', but short of 'infinity' */		while (infcount-- > 3)		  {		    _ungetc_r (rptr, *--p, fp); /* [iInNtT] */		    --nread;		  }	      else		{		  while (p > buf)		    {		      _ungetc_r (rptr, *--p, fp); /* [-+iInN] */		      --nread;		    }		  goto match_failure;		}	    }	  /*	   * If no digits, might be missing exponent digits	   * (just give back the exponent) or might be missing	   * regular digits, but had sign and/or decimal point.	   */	  if (flags & NDIGITS)	    {	      if (flags & EXPOK)		{		  /* no digits at all */		  while (p > buf)		    {		      _ungetc_r (rptr, *--p, fp); /* [-+.] */		      --nread;		    }		  goto match_failure;		}	      /* just a bad exponent (e and maybe sign) */	      c = *--p;	      --nread;	      if (c != 'e' && c != 'E')		{		  _ungetc_r (rptr, c, fp); /* [-+] */		  c = *--p;		  --nread;		}	      _ungetc_r (rptr, c, fp); /* [eE] */	    }	  if ((flags & SUPPRESS) == 0)	    {	      double res = 0;#ifdef _NO_LONGDBL#define QUAD_RES res;#else  /* !_NO_LONG_DBL */	      long double qres = 0;#define QUAD_RES qres;#endif /* !_NO_LONG_DBL */	      long new_exp = 0;	      *p = 0;	      if ((flags & (DPTOK | EXPOK)) == EXPOK)		{		  exp_adjust = zeroes - leading_zeroes;		  new_exp = -exp_adjust;		  exp_start = p;		}	      else if (exp_adjust)                new_exp = _strtol_r (rptr, (exp_start + 1), NULL, 10) - exp_adjust;	      if (exp_adjust)		{		  /* If there might not be enough space for the new exponent,		     truncate some trailing digits to make room.  */		  if (exp_start >= buf + sizeof (buf) - MAX_LONG_LEN)		    exp_start = buf + sizeof (buf) - MAX_LONG_LEN - 1;                 sprintf (exp_start, "e%ld", new_exp);		}	      /* Current _strtold routine is markedly slower than 	         _strtod_r.  Only use it if we have a long double	         result.  */#ifndef _NO_LONGDBL /* !_NO_LONGDBL */	      if (flags & LONGDBL)		qres = _strtold (buf, NULL);	      else#endif	        res = _strtod_r (rptr, buf, NULL);	      if (flags & LONG)		{		  dp = GET_ARG (N, ap, double *);		  *dp = res;		}	      else if (flags & LONGDBL)		{		  ldp = GET_ARG (N, ap, _LONG_DOUBLE *);		  *ldp = QUAD_RES;		}	      else		{		  flp = GET_ARG (N, ap, float *);		  if (isnan (res))		    *flp = nanf (NULL);		  else		    *flp = res;		}	      nassigned++;	    }	  break;	}#endif /* FLOATING_POINT */	}    }input_failure:  /* On read failure, return EOF failure regardless of matches; errno     should have been set prior to here.  On EOF failure (including     invalid format string), return EOF if no matches yet, else number     of matches made prior to failure.  */  _funlockfile (fp);  return nassigned && !(fp->_flags & __SERR) ? nassigned : EOF;match_failure:all_done:  /* Return number of matches, which can be 0 on match failure.  */  _funlockfile (fp);  return nassigned;}#ifndef _NO_POS_ARGS/* Process all intermediate arguments.  Fortunately, with scanf, all   intermediate arguments are sizeof(void*), so we don't need to scan   ahead in the format string.  */static void *get_arg (int n, va_list *ap, int *numargs_p, void **args){  int numargs = *numargs_p;  while (n >= numargs)    args[numargs++] = va_arg (*ap, void *);  *numargs_p = numargs;  return args[n];}#endif /* !_NO_POS_ARGS */

⌨️ 快捷键说明

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