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

📄 vfscanf.c

📁 在x86平台上运行不可信任代码的sandbox。
💻 C
📖 第 1 页 / 共 2 页
字号:
							goto input_failure;						break;					}				}				n = p - p0;				if (n == 0)					goto match_failure;				*p = 0;				nassigned++;			}			nread += n;			break;		case CT_STRING:			/* like CCL, but zero-length string OK, & no NOSKIP */			if (width == 0)				width = (size_t)~0;			if (flags & SUPPRESS) {				n = 0;				while (!isspace(*fp->_p)) {					n++, fp->_r--, fp->_p++;					if (--width == 0)						break;					if (fp->_r <= 0 && __srefill(fp))						break;				}				nread += n;			} else {				p0 = p = va_arg(ap, char *);				while (!isspace(*fp->_p)) {					fp->_r--;					*p++ = *fp->_p++;					if (--width == 0)						break;					if (fp->_r <= 0 && __srefill(fp))						break;				}				*p = 0;				nread += p - p0;				nassigned++;			}			continue;		case CT_INT:			/* scan an integer as if by strtoq/strtouq */#ifdef hardway			if (width == 0 || width > sizeof(buf) - 1)				width = sizeof(buf) - 1;#else			/* size_t is unsigned, hence this optimisation */			if (--width > sizeof(buf) - 2)				width = sizeof(buf) - 2;			width++;#endif			flags |= SIGNOK | NDIGITS | NZDIGITS;			for (p = buf; width; width--) {				c = *fp->_p;				/*				 * Switch on the character; `goto ok'				 * if we accept it as a part of number.				 */				switch (c) {				/*				 * The digit 0 is always legal, but is				 * special.  For %i conversions, if no				 * digits (zero or nonzero) have been				 * scanned (only signs), we will have				 * base==0.  In that case, we should set				 * it to 8 and enable 0x prefixing.				 * Also, if we have not scanned zero digits				 * before this, do not turn off prefixing				 * (someone else will turn it off if we				 * have scanned any nonzero digits).				 */				case '0':					if (base == 0) {						base = 8;						flags |= PFXOK;					}					if (flags & NZDIGITS)					    flags &= ~(SIGNOK|NZDIGITS|NDIGITS);					else					    flags &= ~(SIGNOK|PFXOK|NDIGITS);					goto ok;				/* 1 through 7 always legal */				case '1': case '2': case '3':				case '4': case '5': case '6': case '7':					base = basefix[base];					flags &= ~(SIGNOK | PFXOK | NDIGITS);					goto ok;				/* digits 8 and 9 ok iff decimal or hex */				case '8': case '9':					base = basefix[base];					if (base <= 8)						break;	/* not legal here */					flags &= ~(SIGNOK | PFXOK | NDIGITS);					goto ok;				/* letters ok iff hex */				case 'A': 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);					goto ok;				/* sign ok only as first character */				case '+': case '-':					if (flags & SIGNOK) {						flags &= ~SIGNOK;						goto ok;					}					break;				/* x ok iff flag still set & 2nd char */				case 'x': case 'X':					if (flags & PFXOK && p == buf + 1) {						base = 16;	/* if %i */						flags &= ~PFXOK;						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;				if (--fp->_r > 0)					fp->_p++;				else if (__srefill(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'.			 */			if (flags & NDIGITS) {				if (p > buf)					(void) ungetc(*(u_char *)--p, fp);				goto match_failure;			}			c = ((u_char *)p)[-1];			if (c == 'x' || c == 'X') {				--p;				(void) ungetc(c, fp);			}			if ((flags & SUPPRESS) == 0) {				u_quad_t res;				*p = 0;				res = (*ccfn)(buf, (char **)NULL, base);				if (flags & POINTER)					*va_arg(ap, void **) =					    (void *)(long)res;				else if (flags & QUAD)					*va_arg(ap, quad_t *) = res;				else if (flags & LONG)					*va_arg(ap, long *) = res;				else if (flags & SHORT)					*va_arg(ap, short *) = res;				else					*va_arg(ap, int *) = res;				nassigned++;			}			nread += p - buf;			break;#ifdef FLOATING_POINT		case CT_FLOAT:			/* scan a floating point number as if by strtod */#ifdef hardway			if (width == 0 || width > sizeof(buf) - 1)				width = sizeof(buf) - 1;#else			/* size_t is unsigned, hence this optimisation */			if (--width > sizeof(buf) - 2)				width = sizeof(buf) - 2;			width++;#endif			flags |= SIGNOK | NDIGITS | DPTOK | EXPOK;			for (p = buf; width; width--) {				c = *fp->_p;				/*				 * This code mimicks the integer conversion				 * code, but is much simpler.				 */				switch (c) {				case '0': case '1': case '2': case '3':				case '4': case '5': case '6': case '7':				case '8': case '9':					flags &= ~(SIGNOK | NDIGITS);					goto fok;				case '+': case '-':					if (flags & SIGNOK) {						flags &= ~SIGNOK;						goto fok;					}					break;				case '.':					if (flags & DPTOK) {						flags &= ~(SIGNOK | DPTOK);						goto fok;					}					break;				case 'e': case 'E':					/* no exponent without some digits */					if ((flags&(NDIGITS|EXPOK)) == EXPOK) {						flags =						    (flags & ~(EXPOK|DPTOK)) |						    SIGNOK | NDIGITS;						goto fok;					}					break;				}				break;		fok:				*p++ = c;				if (--fp->_r > 0)					fp->_p++;				else if (__srefill(fp))					break;	/* EOF */			}			/*			 * 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(*(u_char *)--p, fp);					goto match_failure;				}				/* just a bad exponent (e and maybe sign) */				c = *(u_char *)--p;				if (c != 'e' && c != 'E') {					(void) ungetc(c, fp);/* sign */					c = *(u_char *)--p;				}				(void) ungetc(c, fp);			}			if ((flags & SUPPRESS) == 0) {				double res;				*p = 0;				res = strtod(buf, (char **) NULL);				if (flags & LONGDBL)					*va_arg(ap, long double *) = res;				else if (flags & LONG)					*va_arg(ap, double *) = res;				else					*va_arg(ap, float *) = res;				nassigned++;			}			nread += p - buf;			break;#endif /* FLOATING_POINT */		}	}input_failure:	return (nassigned ? nassigned : -1);match_failure:	return (nassigned);}/* * Fill in the given table from the scanset at the given format * (just after `[').  Return a pointer to the character past the * closing `]'.  The table has a 1 wherever characters should be * considered part of the scanset. */static u_char *__sccl(tab, fmt)	register char *tab;	register u_char *fmt;{	register int c, n, v;	/* first `clear' the whole table */	c = *fmt++;		/* first char hat => negated scanset */	if (c == '^') {		v = 1;		/* default => accept */		c = *fmt++;	/* get new first char */	} else		v = 0;		/* default => reject */	/* should probably use memset here */	for (n = 0; n < 256; n++)		tab[n] = v;	if (c == 0)		return (fmt - 1);/* format ended before closing ] */	/*	 * Now set the entries corresponding to the actual scanset	 * to the opposite of the above.	 *	 * The first character may be ']' (or '-') without being special;	 * the last character may be '-'.	 */	v = 1 - v;	for (;;) {		tab[c] = v;		/* take character c */doswitch:		n = *fmt++;		/* and examine the next */		switch (n) {		case 0:			/* format ended too soon */			return (fmt - 1);		case '-':			/*			 * A scanset of the form			 *	[01+-]			 * is defined as `the digit 0, the digit 1,			 * the character +, the character -', but			 * the effect of a scanset such as			 *	[a-zA-Z0-9]			 * is implementation defined.  The V7 Unix			 * scanf treats `a-z' as `the letters a through			 * z', but treats `a-a' as `the letter a, the			 * character -, and the letter a'.			 *			 * For compatibility, the `-' is not considerd			 * to define a range if the character following			 * it is either a close bracket (required by ANSI)			 * or is not numerically greater than the character			 * we just stored in the table (c).			 */			n = *fmt;			if (n == ']' || n < c) {				c = '-';				break;	/* resume the for(;;) */			}			fmt++;			do {		/* fill in the range */				tab[++c] = v;			} while (c < n);#if 1	/* XXX another disgusting compatibility hack */			/*			 * Alas, the V7 Unix scanf also treats formats			 * such as [a-c-e] as `the letters a through e'.			 * This too is permitted by the standard....			 */			goto doswitch;#else			c = *fmt++;			if (c == 0)				return (fmt - 1);			if (c == ']')				return (fmt);#endif			break;		case ']':		/* end of scanset */			return (fmt);		default:		/* just another character */			c = n;			break;		}	}	/* NOTREACHED */}

⌨️ 快捷键说明

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