subr_scanf.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 794 行 · 第 1/2 页

C
794
字号
/*- * Copyright (c) 1990, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: subr_scanf.c,v 1.1.2.1 1999/01/29 06:39:23 dillon Exp $ * From: Id: vfscanf.c,v 1.13 1998/09/25 12:20:27 obrien Exp  */#include <sys/param.h>#include <sys/systm.h>#include <sys/kernel.h>#include <machine/limits.h>/* * Note that stdarg.h and the ANSI style va_start macro is used for both * ANSI and traditional C compilers. */#include <machine/stdarg.h>#define	BUF		32 	/* Maximum length of numeric string. *//* * Flags used during conversion. */#define	LONG		0x01	/* l: long or double */#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 */#define	QUAD		0x400/* * 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., strtoq or strtouq */typedef u_quad_t (*ccfntype)(const char *, char **, int);#define isspace(c)	((c) == ' ' || (c) == '\t' || \			 (c) == '\r' || (c) == '\n')#define isascii(c)	(((c) & ~0x7f) == 0)#define isupper(c)	((c) >= 'A' && (c) <= 'Z')#define islower(c)	((c) >= 'a' && (c) <= 'z')#define isalpha(c)	(isupper(c) || (islower(c)))#define isdigit(c)	((c) >= '0' && (c) <= '9')static u_char *__sccl(char *, u_char *);intsscanf(const char *ibuf, const char *fmt, ...){	va_list ap;	int ret;		va_start(ap, fmt);	ret = vsscanf(ibuf, fmt, ap);	va_end(ap);	return(ret);}intvsscanf(const char *inp, char const *fmt0, va_list ap){	int inr;	u_char *fmt = (u_char *)fmt0;	int c;			/* character from format, or conversion */	size_t width;		/* field width, or 0 */	char *p;		/* points into all kinds of strings */	int n;			/* handy integer */	int flags;		/* flags as defined above */	char *p0;		/* saves original value of p when necessary */	int nassigned;		/* number of fields assigned */	int nconversions;	/* number of conversions */	int nread;		/* number of characters consumed from fp */	int base;		/* base argument to strtoq/strtouq */	ccfntype 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 };	inr = strlen(inp);		nassigned = 0;	nconversions = 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 (inr > 0 && isspace(*inp))				nread++, inr--, inp++;			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 (inr <= 0)				goto input_failure;			if (*inp != c)				goto match_failure;			inr--, inp++;			nread++;			continue;		case '*':			flags |= SUPPRESS;			goto again;		case 'l':			flags |= LONG;			goto again;		case 'q':			flags |= QUAD;			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.		 *		 */		case 'd':			c = CT_INT;			ccfn = (ccfntype)strtoq;			base = 10;			break;		case 'i':			c = CT_INT;			ccfn = (ccfntype)strtoq;			base = 0;			break;		case 'o':			c = CT_INT;			ccfn = strtouq;			base = 8;			break;		case 'u':			c = CT_INT;			ccfn = strtouq;			base = 10;			break;		case 'x':			flags |= PFXOK;	/* enable 0x prefixing */			c = CT_INT;			ccfn = strtouq;			base = 16;			break;		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':			nconversions++;			if (flags & SUPPRESS)	/* ??? */				continue;			if (flags & SHORT)				*va_arg(ap, short *) = nread;			else if (flags & LONG)				*va_arg(ap, long *) = nread;			else if (flags & QUAD)				*va_arg(ap, quad_t *) = nread;			else				*va_arg(ap, int *) = nread;			continue;		}		/*		 * We have a conversion that requires input.		 */		if (inr <= 0)			goto input_failure;		/*		 * Consume leading white space, except for formats		 * that suppress this.		 */		if ((flags & NOSKIP) == 0) {			while (isspace(*inp)) {				nread++;				if (--inr > 0)					inp++;				else 					goto input_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)				width = 1;			if (flags & SUPPRESS) {				size_t sum = 0;				for (;;) {					if ((n = inr) < width) {						sum += n;						width -= n;						inp += n;						if (sum == 0)							goto input_failure;							break;					} else {						sum += width;						inr -= width;						inp += width;						break;					}				}				nread += sum;			} else {				bcopy(inp, va_arg(ap, char *), width);				inr -= width;				inp += width;				nread += width;				nassigned++;			}			nconversions++;			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[(unsigned char)*inp]) {					n++, inr--, inp++;					if (--width == 0)						break;					if (inr <= 0) {						if (n == 0)							goto input_failure;						break;					}				}				if (n == 0)					goto match_failure;			} else {				p0 = p = va_arg(ap, char *);				while (ccltab[(unsigned char)*inp]) {					inr--;					*p++ = *inp++;					if (--width == 0)						break;					if (inr <= 0) {						if (p == p0)							goto input_failure;						break;					}				}				n = p - p0;				if (n == 0)					goto match_failure;				*p = 0;				nassigned++;			}			nread += n;			nconversions++;			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(*inp)) {					n++, inr--, inp++;					if (--width == 0)						break;					if (inr <= 0)						break;				}				nread += n;			} else {				p0 = p = va_arg(ap, char *);				while (!isspace(*inp)) {					inr--;					*p++ = *inp++;					if (--width == 0)						break;					if (inr <= 0)						break;				}				*p = 0;				nread += p - p0;				nassigned++;			}			nconversions++;			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

⌨️ 快捷键说明

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