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

📄 sbufvscan.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley.  The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */// Extensively hacked for GNU iostream by Per Bothner 1991, 1992.// Changes copyright Per Bothner 1992.#if defined(LIBC_SCCS) && !defined(lint)static char sccsid[] = "%W% (Berkeley) %G%";#endif /* LIBC_SCCS and not lint */#include <ioprivate.h>#include <ctype.h>#ifndef NO_STDARG#include <stdarg.h>#else#include <varargs.h>#endif#ifndef	NO_FLOATING_POINT#define FLOATING_POINT#endif#ifdef FLOATING_POINT#include "floatio.h"#define	BUF	(MAXEXP+MAXFRACT+3)	/* 3 = sign + decimal point + NUL */#else#define	BUF	40#endif/* * Flags used during conversion. */#define	LONG		0x01	/* l: long or double */#define	LONGDBL		0x02	/* L: long double; unimplemented */#define	SHORT		0x04	/* h: short */#define	SUPPRESS	0x08	/* suppress assignment */#define	POINTER		0x10	/* weird %p pointer (`fake hex') */#define	NOSKIP		0x20	/* do not skip blanks *//* * The following are used in numeric conversions only: * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point; * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral. */#define	SIGNOK		0x40	/* +/- is (still) legal */#define	NDIGITS		0x80	/* no digits detected */#define	DPTOK		0x100	/* (float) decimal point is still legal */#define	EXPOK		0x200	/* (float) exponent (e+3, etc) still legal */#define	PFXOK		0x100	/* 0x prefix is (still) legal */#define	NZDIGITS	0x200	/* no zero digits detected *//* * Conversion types. */#define	CT_CHAR		0	/* %c conversion */#define	CT_CCL		1	/* %[...] conversion */#define	CT_STRING	2	/* %s conversion */#define	CT_INT		3	/* integer, i.e., strtol or strtoul */#define	CT_FLOAT	4	/* floating, i.e., strtod */#define u_char unsigned char#define u_long unsigned longextern "C" u_long strtoul(const char*, char**, int);static const u_char *__sccl(register char *tab, register const u_char *fmt);// If state is non-NULL, set failbit and/or eofbit as appropriate.int streambuf::vscan(char const *fmt0,		     _G_va_list ap,		     ios *stream /* = NULL */){	register const u_char *fmt = (const 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 */	// Assignments to base and ccfn are just to suppress warnings from gcc.	int base = 0;		/* base argument to strtol/strtoul */	u_long (*ccfn)(const char*, char**, int) = 0;	// conversion function (strtol/strtoul)	char ccltab[256];	/* character class table for %[...] */	char buf[BUF];		/* buffer for numeric conversions */	int seen_eof = 0;	/* `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;	for (;;) {		c = *fmt++;		if (c == 0)			goto done;		if (isspace(c)) {			for (;;) {			        c = sbumpc();				if (c == EOF)				    goto eof_failure;				if (!isspace(c)) {				    sputbackc(c);				    break;				}				nread++;			}			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:		        n = sbumpc();			if (n == EOF)			    goto eof_failure;			if (n != c) {			    sputbackc(n);			    goto match_failure;			}			nread++;			continue;		case '*':			flags |= SUPPRESS;			goto again;		case 'l':			flags |= LONG;			goto again;		case 'L':			flags |= LONGDBL;			goto again;		case 'h':			flags |= SHORT;			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 = (u_long (*)(const char, char**, int))strtol;			base = 10;			break;		case 'i':			c = CT_INT;			ccfn = (u_long (*)(const char, char**, int))strtol;			base = 0;			break;		case 'O':	/* compat */			flags |= LONG;			/* FALLTHROUGH */		case 'o':			c = CT_INT;			ccfn = strtoul;			base = 8;			break;		case 'u':			c = CT_INT;			ccfn = strtoul;			base = 10;			break;		case 'X':	/* compat   XXX */			flags |= LONG;			/* FALLTHROUGH */		case 'x':			flags |= PFXOK;	/* enable 0x prefixing */			c = CT_INT;			ccfn = strtoul;			base = 16;			break;#ifdef FLOATING_POINT		case 'E':	/* compat   XXX */		case 'F':	/* compat */			flags |= LONG;			/* FALLTHROUGH */		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 = strtoul;			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 */		        nassigned = EOF;			goto done;		default:	/* compat */			if (isupper(c))				flags |= LONG;			c = CT_INT;			ccfn = (u_long (*)(const char, char**, int))strtol;			base = 10;			break;		}		/*		 * We have a conversion that requires input.		 */		if (sgetc() == EOF)			goto eof_failure;		/*		 * Consume leading white space, except for formats		 * that suppress this.		 */		if ((flags & NOSKIP) == 0) {		    n = *_gptr;		    while (isspace(n)) {			_gptr++;			nread++;			n = sgetc();			if (n == EOF)			    goto eof_failure;		    }		    // Note that there is at least one character in		    // the buffer, so conversions that do not set NOSKIP		    // can no longer result in an input failure.		}		/*		 * Do the conversion.		 */		switch (c) {		case CT_CHAR:			/* scan arbitrary characters (sets NOSKIP) */			if (width == 0) // FIXME!				width = 1;			if (flags & SUPPRESS) {			    size_t sum = 0;			    for (;;) {				if ((n = _egptr - _gptr) < (int)width) {				    sum += n;				    width -= n;				    _gptr += n;				    if (underflow() == EOF)					if (sum == 0)					    goto eof_failure;					else {					    seen_eof++;					    break;					}				} else {				    sum += width;				    _gptr += width;				    break;				}			    }			    nread += sum;			} else {			    size_t r = sgetn((char*)va_arg(ap, char*),						 width);			    if (r != width)				goto eof_failure;			    nread += r;			    nassigned++;			}			break;		case CT_CCL:			/* scan a (nonempty) character class (sets NOSKIP) */			if (width == 0)				width = ~0;	/* `infinity' */			/* take only those things in the class */			if (flags & SUPPRESS) {				n = 0;				while (ccltab[*_gptr]) {				    n++, _gptr++;				    if (--width == 0)					break;				    if (sgetc() == EOF) {					if (n == 0)					    goto eof_failure;					seen_eof++;					break;				    }				}				if (n == 0)					goto match_failure;			} else {			    p0 = p = va_arg(ap, char *);			    while (ccltab[*_gptr]) {				*p++ = *_gptr++;				if (--width == 0)				    break;				if (sgetc() == EOF) {				    if (p == p0)					goto eof_failure;				    seen_eof++;				    break;				}			    }			    n = p - p0;			    if (n == 0)				goto match_failure;			    *p = 0;			    nassigned++;

⌨️ 快捷键说明

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