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

📄 vsprintf.c

📁 Lib files of linux kernel
💻 C
📖 第 1 页 / 共 2 页
字号:
{	unsigned long long num;	int base;	char *str, *end, c;	int flags;		/* flags to number() */	int field_width;	/* width of output field */	int precision;		/* min. # of digits for integers; max				   number of chars for from string */	int qualifier;		/* 'h', 'l', or 'L' for integer fields */				/* 'z' support added 23/7/1999 S.H.    */				/* 'z' changed to 'Z' --davidm 1/25/99 */				/* 't' added for ptrdiff_t */	/* Reject out-of-range values early.  Large positive sizes are	   used for unknown buffer sizes. */	if (unlikely((int) size < 0)) {		/* There can be only one.. */		static char warn = 1;		WARN_ON(warn);		warn = 0;		return 0;	}	str = buf;	end = buf + size;	/* Make sure end is always >= buf */	if (end < buf) {		end = ((void *)-1);		size = end - buf;	}	for (; *fmt ; ++fmt) {		if (*fmt != '%') {			if (str < end)				*str = *fmt;			++str;			continue;		}		/* process flags */		flags = 0;		repeat:			++fmt;		/* this also skips first '%' */			switch (*fmt) {				case '-': flags |= LEFT; goto repeat;				case '+': flags |= PLUS; goto repeat;				case ' ': flags |= SPACE; goto repeat;				case '#': flags |= SPECIAL; goto repeat;				case '0': flags |= ZEROPAD; goto repeat;			}		/* get field width */		field_width = -1;		if (isdigit(*fmt))			field_width = skip_atoi(&fmt);		else if (*fmt == '*') {			++fmt;			/* it's the next argument */			field_width = va_arg(args, int);			if (field_width < 0) {				field_width = -field_width;				flags |= LEFT;			}		}		/* get the precision */		precision = -1;		if (*fmt == '.') {			++fmt;				if (isdigit(*fmt))				precision = skip_atoi(&fmt);			else if (*fmt == '*') {				++fmt;				/* it's the next argument */				precision = va_arg(args, int);			}			if (precision < 0)				precision = 0;		}		/* get the conversion qualifier */		qualifier = -1;		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||		    *fmt =='Z' || *fmt == 'z' || *fmt == 't') {			qualifier = *fmt;			++fmt;			if (qualifier == 'l' && *fmt == 'l') {				qualifier = 'L';				++fmt;			}		}		/* default base */		base = 10;		switch (*fmt) {			case 'c':				if (!(flags & LEFT)) {					while (--field_width > 0) {						if (str < end)							*str = ' ';						++str;					}				}				c = (unsigned char) va_arg(args, int);				if (str < end)					*str = c;				++str;				while (--field_width > 0) {					if (str < end)						*str = ' ';					++str;				}				continue;			case 's':				str = string(str, end, va_arg(args, char *), field_width, precision, flags);				continue;			case 'p':				str = pointer(fmt+1, str, end,						va_arg(args, void *),						field_width, precision, flags);				/* Skip all alphanumeric pointer suffixes */				while (isalnum(fmt[1]))					fmt++;				continue;			case 'n':				/* FIXME:				* What does C99 say about the overflow case here? */				if (qualifier == 'l') {					long * ip = va_arg(args, long *);					*ip = (str - buf);				} else if (qualifier == 'Z' || qualifier == 'z') {					size_t * ip = va_arg(args, size_t *);					*ip = (str - buf);				} else {					int * ip = va_arg(args, int *);					*ip = (str - buf);				}				continue;			case '%':				if (str < end)					*str = '%';				++str;				continue;				/* integer number formats - set up the flags and "break" */			case 'o':				base = 8;				break;			case 'x':				flags |= SMALL;			case 'X':				base = 16;				break;			case 'd':			case 'i':				flags |= SIGN;			case 'u':				break;			default:				if (str < end)					*str = '%';				++str;				if (*fmt) {					if (str < end)						*str = *fmt;					++str;				} else {					--fmt;				}				continue;		}		if (qualifier == 'L')			num = va_arg(args, long long);		else if (qualifier == 'l') {			num = va_arg(args, unsigned long);			if (flags & SIGN)				num = (signed long) num;		} else if (qualifier == 'Z' || qualifier == 'z') {			num = va_arg(args, size_t);		} else if (qualifier == 't') {			num = va_arg(args, ptrdiff_t);		} else if (qualifier == 'h') {			num = (unsigned short) va_arg(args, int);			if (flags & SIGN)				num = (signed short) num;		} else {			num = va_arg(args, unsigned int);			if (flags & SIGN)				num = (signed int) num;		}		str = number(str, end, num, base,				field_width, precision, flags);	}	if (size > 0) {		if (str < end)			*str = '\0';		else			end[-1] = '\0';	}	/* the trailing null byte doesn't count towards the total */	return str-buf;}EXPORT_SYMBOL(vsnprintf);/** * vscnprintf - Format a string and place it in a buffer * @buf: The buffer to place the result into * @size: The size of the buffer, including the trailing null space * @fmt: The format string to use * @args: Arguments for the format string * * The return value is the number of characters which have been written into * the @buf not including the trailing '\0'. If @size is <= 0 the function * returns 0. * * Call this function if you are already dealing with a va_list. * You probably want scnprintf() instead. */int vscnprintf(char *buf, size_t size, const char *fmt, va_list args){	int i;	i=vsnprintf(buf,size,fmt,args);	return (i >= size) ? (size - 1) : i;}EXPORT_SYMBOL(vscnprintf);/** * snprintf - Format a string and place it in a buffer * @buf: The buffer to place the result into * @size: The size of the buffer, including the trailing null space * @fmt: The format string to use * @...: Arguments for the format string * * The return value is the number of characters which would be * generated for the given input, excluding the trailing null, * as per ISO C99.  If the return is greater than or equal to * @size, the resulting string is truncated. */int snprintf(char * buf, size_t size, const char *fmt, ...){	va_list args;	int i;	va_start(args, fmt);	i=vsnprintf(buf,size,fmt,args);	va_end(args);	return i;}EXPORT_SYMBOL(snprintf);/** * scnprintf - Format a string and place it in a buffer * @buf: The buffer to place the result into * @size: The size of the buffer, including the trailing null space * @fmt: The format string to use * @...: Arguments for the format string * * The return value is the number of characters written into @buf not including * the trailing '\0'. If @size is <= 0 the function returns 0. */int scnprintf(char * buf, size_t size, const char *fmt, ...){	va_list args;	int i;	va_start(args, fmt);	i = vsnprintf(buf, size, fmt, args);	va_end(args);	return (i >= size) ? (size - 1) : i;}EXPORT_SYMBOL(scnprintf);/** * vsprintf - Format a string and place it in a buffer * @buf: The buffer to place the result into * @fmt: The format string to use * @args: Arguments for the format string * * The function returns the number of characters written * into @buf. Use vsnprintf() or vscnprintf() in order to avoid * buffer overflows. * * Call this function if you are already dealing with a va_list. * You probably want sprintf() instead. */int vsprintf(char *buf, const char *fmt, va_list args){	return vsnprintf(buf, INT_MAX, fmt, args);}EXPORT_SYMBOL(vsprintf);/** * sprintf - Format a string and place it in a buffer * @buf: The buffer to place the result into * @fmt: The format string to use * @...: Arguments for the format string * * The function returns the number of characters written * into @buf. Use snprintf() or scnprintf() in order to avoid * buffer overflows. */int sprintf(char * buf, const char *fmt, ...){	va_list args;	int i;	va_start(args, fmt);	i=vsnprintf(buf, INT_MAX, fmt, args);	va_end(args);	return i;}EXPORT_SYMBOL(sprintf);/** * vsscanf - Unformat a buffer into a list of arguments * @buf:	input buffer * @fmt:	format of buffer * @args:	arguments */int vsscanf(const char * buf, const char * fmt, va_list args){	const char *str = buf;	char *next;	char digit;	int num = 0;	int qualifier;	int base;	int field_width;	int is_sign = 0;	while(*fmt && *str) {		/* skip any white space in format */		/* white space in format matchs any amount of		 * white space, including none, in the input.		 */		if (isspace(*fmt)) {			while (isspace(*fmt))				++fmt;			while (isspace(*str))				++str;		}		/* anything that is not a conversion must match exactly */		if (*fmt != '%' && *fmt) {			if (*fmt++ != *str++)				break;			continue;		}		if (!*fmt)			break;		++fmt;				/* skip this conversion.		 * advance both strings to next white space		 */		if (*fmt == '*') {			while (!isspace(*fmt) && *fmt)				fmt++;			while (!isspace(*str) && *str)				str++;			continue;		}		/* get field width */		field_width = -1;		if (isdigit(*fmt))			field_width = skip_atoi(&fmt);		/* get conversion qualifier */		qualifier = -1;		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||		    *fmt == 'Z' || *fmt == 'z') {			qualifier = *fmt++;			if (unlikely(qualifier == *fmt)) {				if (qualifier == 'h') {					qualifier = 'H';					fmt++;				} else if (qualifier == 'l') {					qualifier = 'L';					fmt++;				}			}		}		base = 10;		is_sign = 0;		if (!*fmt || !*str)			break;		switch(*fmt++) {		case 'c':		{			char *s = (char *) va_arg(args,char*);			if (field_width == -1)				field_width = 1;			do {				*s++ = *str++;			} while (--field_width > 0 && *str);			num++;		}		continue;		case 's':		{			char *s = (char *) va_arg(args, char *);			if(field_width == -1)				field_width = INT_MAX;			/* first, skip leading white space in buffer */			while (isspace(*str))				str++;			/* now copy until next white space */			while (*str && !isspace(*str) && field_width--) {				*s++ = *str++;			}			*s = '\0';			num++;		}		continue;		case 'n':			/* return number of characters read so far */		{			int *i = (int *)va_arg(args,int*);			*i = str - buf;		}		continue;		case 'o':			base = 8;			break;		case 'x':		case 'X':			base = 16;			break;		case 'i':                        base = 0;		case 'd':			is_sign = 1;		case 'u':			break;		case '%':			/* looking for '%' in str */			if (*str++ != '%') 				return num;			continue;		default:			/* invalid format; stop here */			return num;		}		/* have some sort of integer conversion.		 * first, skip white space in buffer.		 */		while (isspace(*str))			str++;		digit = *str;		if (is_sign && digit == '-')			digit = *(str + 1);		if (!digit                    || (base == 16 && !isxdigit(digit))                    || (base == 10 && !isdigit(digit))                    || (base == 8 && (!isdigit(digit) || digit > '7'))                    || (base == 0 && !isdigit(digit)))				break;		switch(qualifier) {		case 'H':	/* that's 'hh' in format */			if (is_sign) {				signed char *s = (signed char *) va_arg(args,signed char *);				*s = (signed char) simple_strtol(str,&next,base);			} else {				unsigned char *s = (unsigned char *) va_arg(args, unsigned char *);				*s = (unsigned char) simple_strtoul(str, &next, base);			}			break;		case 'h':			if (is_sign) {				short *s = (short *) va_arg(args,short *);				*s = (short) simple_strtol(str,&next,base);			} else {				unsigned short *s = (unsigned short *) va_arg(args, unsigned short *);				*s = (unsigned short) simple_strtoul(str, &next, base);			}			break;		case 'l':			if (is_sign) {				long *l = (long *) va_arg(args,long *);				*l = simple_strtol(str,&next,base);			} else {				unsigned long *l = (unsigned long*) va_arg(args,unsigned long*);				*l = simple_strtoul(str,&next,base);			}			break;		case 'L':			if (is_sign) {				long long *l = (long long*) va_arg(args,long long *);				*l = simple_strtoll(str,&next,base);			} else {				unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*);				*l = simple_strtoull(str,&next,base);			}			break;		case 'Z':		case 'z':		{			size_t *s = (size_t*) va_arg(args,size_t*);			*s = (size_t) simple_strtoul(str,&next,base);		}		break;		default:			if (is_sign) {				int *i = (int *) va_arg(args, int*);				*i = (int) simple_strtol(str,&next,base);			} else {				unsigned int *i = (unsigned int*) va_arg(args, unsigned int*);				*i = (unsigned int) simple_strtoul(str,&next,base);			}			break;		}		num++;		if (!next)			break;		str = next;	}	/*	 * Now we've come all the way through so either the input string or the	 * format ended. In the former case, there can be a %n at the current	 * position in the format that needs to be filled.	 */	if (*fmt == '%' && *(fmt + 1) == 'n') {		int *p = (int *)va_arg(args, int *);		*p = str - buf;	}	return num;}EXPORT_SYMBOL(vsscanf);/** * sscanf - Unformat a buffer into a list of arguments * @buf:	input buffer * @fmt:	formatting of buffer * @...:	resulting arguments */int sscanf(const char * buf, const char * fmt, ...){	va_list args;	int i;	va_start(args,fmt);	i = vsscanf(buf,fmt,args);	va_end(args);	return i;}EXPORT_SYMBOL(sscanf);

⌨️ 快捷键说明

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