rem: ccfn = (uint64 (*)())strtoq;
add: ccfn = (uint64 (*)())strtoll;
context: __svfscanf(fp, fmt0, ap)	register FILE *fp;	char const *fmt0;	va_list ap;{	register u_char *fmt = (u_char *)fmt0;	register int c;		/* character from format, or conversion */	register size_t width;	/* field width, or 0 */	register char *p;	/* points into all kinds of strings */	register int n;		/* handy integer */	register int flags;	/* flags as defined above */	register char *p0;	/* saves original value of p when necessary */	int nassigned;		/* number of fields assigned */	int nread;		/* number of characters consumed from fp */	int base;		/* base argument to strtoq/strtouq */	uint64 (*ccfn)();	/* conversion function (strtoq/strtouq) */	char ccltab[256];	/* character class table for %[...] */	char buf[BUF];		/* buffer for numeric conversions */	/* `basefix' is used to avoid `if' tests in the integer scanner */	static short basefix[17] =		{ 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };	nassigned = 0;	nread = 0;	base = 0;		/* XXX just to keep gcc happy */	ccfn = NULL;		/* XXX just to keep gcc happy */	for (;;) {		c = *fmt++;		if (c == 0)			return (nassigned);		if (isspace(c)) {			while ((fp->_r > 0 || __srefill(fp) == 0) &&			    isspace(*fp->_p))				nread++, fp->_r--, fp->_p++;			continue;		}		if (c != '%')			goto literal;		width = 0;		flags = 0;		/*		 * switch on the format.  continue if done;		 * break once format type is derived.		 */again:		c = *fmt++;		switch (c) {		case '%':literal:			if (fp->_r <= 0 && __srefill(fp))				goto input_failure;			if (*fp->_p != c)				goto match_failure;			fp->_r--, fp->_p++;			nread++;			continue;		case '*':			flags |= SUPPRESS;			goto again;		case 'L':			flags |= LONGDBL;			goto again;		case 'h':			flags |= SHORT;			goto again;		case 'l':			if (*fmt == 'l') {				fmt++;				flags |= QUAD;			} else {				flags |= LONG;			}			goto again;		case 'q':			flags |= QUAD;			goto again;		case '0': case '1': case '2': case '3': case '4':		case '5': case '6': case '7': case '8': case '9':			width = width * 10 + c - '0';			goto again;		/*		 * Conversions.		 * Those marked `compat' are for 4.[123]BSD compatibility.		 *		 * (According to ANSI, E and X formats are supposed		 * to the same as e and x.  Sorry about that.)		 */		case 'D':	/* compat */			flags |= LONG;			/* FALLTHROUGH */		case 'd':			c = CT_INT;			ccfn = (uint64 (*)())strtoq;			base = 10;			break;		case 'i':			c = CT_INT;			ccfn = (uint64 (*)())strtoq;			base = 0;			break;		case 'O':	/* compat */			flags |= LONG;			/* FALLTHROUGH */		case 'o':			c = CT_INT;			ccfn = strtouq;			base = 8;			break;		case 'u':			c = CT_INT;			ccfn = strtouq;			base = 10;			break;		case 'X':		case 'x':			flags |= PFXOK;	/* enable 0x prefixing */			c = CT_INT;			ccfn = strtouq;			base = 16;			break;#ifdef FLOATING_POINT		case 'E':		case 'G':		case 'e': 		case 'f': 		case 'g':			c = CT_FLOAT;			break;#endif		case 's':			c = CT_STRING;			break;		case '[':			fmt = __sccl(ccltab, fmt);			flags |= NOSKIP;			c = CT_CCL;			break;		case 'c':			flags |= NOSKIP;			c = CT_CHAR;			break;		case 'p':	/* pointer format is like hex */			flags |= POINTER | PFXOK;			c = CT_INT;			ccfn = strtouq;			base = 16;			break;		case 'n':			if (flags & SUPPRESS)	/* ??? */				continue;			if (flags & SHORT)				*va_arg(ap, short *) = nread;			else if (flags & LONG)				*va_arg(ap, long *) = nread;			else				*va_arg(ap, int *) = nread;			continue;		/*		 * Disgusting backwards compatibility hacks.	XXX		 */		case '\0':	/* compat */			return (EOF);		default:	/* compat */			if (isupper(c))				flags |= LONG;			c = CT_INT;			ccfn = (uint64 (*)())strtoq;			base = 10;			break;		}		/*		 * We have a conversion that requires input.		 */		if (fp->_r <= 0 && __srefill(fp))			goto input_failure;		/*		 * Consume leading white space, except for formats		 * that suppress this.		 */		if ((flags & NOSKIP) == 0) {			while (isspace(*fp->_p)) {				nread++;				if (--fp->_r > 0)					fp->_p++;				else if (__srefill(fp))					goto input_failure;			}			/*			 * Note that there is at least one character in			 * the buffer, so conversions that do not set NOSKIP			 * ca no longer result in an input failure.			 */		}		/*		 * Do the conversion.		 */		switch (c) {		case CT_CHAR:			/* scan arbitrary characters (sets NOSKIP) */			if (width == 0)				width = 1;			if (flags & SUPPRESS) {				size_t sum = 0;				for (;;) {					if ((n = fp->_r) < width) {						sum += n;						width -= n;						fp->_p += n;						if (__srefill(fp)) {							if (sum == 0)							    goto input_failure;							break;						}					} else {						sum += width;						fp->_r -= width;						fp->_p += width;						break;					}				}				nread += sum;			} else {				size_t r = fread((void *)va_arg(ap, char *), 1,				    width, fp);				if (r == 0)					goto input_failure;				nread += r;				nassigned++;			}			break;		case CT_CCL:			/* scan a (nonempty) character class (sets NOSKIP) */			if (width == 0)				width = (size_t)~0;	/* `infinity' */			/* take only those things in the class */			if (flags & SUPPRESS) {				n = 0;				while (ccltab[*fp->_p]) {					n++, fp->_r--, fp->_p++;					if (--width == 0)						break;					if (fp->_r <= 0 && __srefill(fp)) {						if (n == 0)							goto input_failure;						break;					}				}				if (n == 0)					goto match_failure;			} else {				p0 = p = va_arg(ap, char *);				while (ccltab[*fp->_p]) {					fp->_r--;					*p++ = *fp->_p++;					if (--width == 0)						break;					if (fp->_r <= 0 && __srefill(fp)) {						if (p == p0)							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) {				uint64 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, int64 *) = 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);}