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

📄 vsprintf.c

📁 YL9200开发板的测试代码,详细请下载后细看
💻 C
字号:
/*
 *  linux/lib/vsprintf.c
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 */

/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
/*
 * Wirzenius wrote this portably, Torvalds fucked it up :-)
 */

#include <stdarg.h>
//#include <linux/types.h>
#include <string.h>
#include <ctype.h>

unsigned long simple_strtoul( const char* cp , char** endp , unsigned int base )
{
	unsigned long result = 0,value;

	if ( *cp == '0' )
	{
		cp++;
		if ( ( *cp == 'x' ) && isxdigit( cp[1] ) )
		{
			base = 16;
			cp++;
		}
		if ( !base )
		{
			base = 8;
		}
	}
	if ( !base )
	{
		base = 10;
	}
	while ( isxdigit( *cp ) &&
		( value = isdigit( *cp ) ? *cp - '0' : ( islower( *cp ) ? toupper( *cp ) : *cp ) - 'A' + 10 ) < base )
	{
		result = result * base + value;
		cp++;
	}
	if ( endp )
		*endp = ( char * ) cp;
	return result;
}

long simple_strtol( const char* cp , char** endp , unsigned int base )
{
	if ( *cp == '-' )
		return -simple_strtoul( cp + 1 , endp , base );
	return simple_strtoul( cp , endp , base );
}

/* we use this so that we can do without the ctype library */
#define is_digit(c)	((c) >= '0' && (c) <= '9')

static int skip_atoi( const char** s )
{
	int i = 0;

	while ( is_digit( **s ) )
		i = i * 10 + *( ( *s )++ ) - '0';
	return i;
}

#define ZEROPAD	1		/* pad with zero */
#define SIGN	2		/* unsigned/signed long */
#define PLUS	4		/* show plus */
#define SPACE	8		/* space if plus */
#define LEFT	16		/* left justified */
#define SPECIAL	32		/* 0x */
#define LARGE	64		/* use 'ABCDEF' instead of 'abcdef' */

#define do_div(n,base) ({ \
			int __res; \
			__res = ((unsigned long) n) % (unsigned) base; \
			n = ((unsigned long) n) / (unsigned) base; \
			__res; })

static char* number( char* str , long num , int base , int size , int precision , int type )
{
	char c, sign, tmp[66];
	const char* digits = "0123456789abcdefghijklmnopqrstuvwxyz";
	int i;

	if ( type & LARGE )
		digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	if ( type & LEFT )
		type &= ~ZEROPAD;
	if ( base <2 || base> 36 )
		return 0;
	c = ( type & ZEROPAD ) ? '0' : ' ';
	sign = 0;
	if ( type & SIGN )
	{
		if ( num < 0 )
		{
			sign = '-';
			num = -num;
			size--;
		}
		else if ( type & PLUS )
		{
			sign = '+';
			size--;
		}
		else if ( type & SPACE )
		{
			sign = ' ';
			size--;
		}
	}
	if ( type & SPECIAL )
	{
		if ( base == 16 )
			size -= 2;
		else if ( base == 8 )
			size--;
	}
	i = 0;
	if ( num == 0 )
		tmp[i++] = '0';
	else
		while ( num != 0 )
		{
			int __res;
			__res = ( ( unsigned long ) num ) % ( unsigned ) base;
			num = ( ( unsigned long ) num ) / ( unsigned ) base;
			tmp[i++] = digits[__res];
			//			tmp[i++] = digits[do_div(num,base)];
		}

	if ( i > precision )
		precision = i;
	size -= precision;
	if ( !( type & ( ZEROPAD + LEFT ) ) )
		while ( size-- > 0 )
			*str++ = ' ';
	if ( sign )
		*str++ = sign;
	if ( type & SPECIAL )
	{
		if ( base == 8 )
			*str++ = '0';
		else if ( base == 16 )
		{
			*str++ = '0';
			*str++ = digits[33];
		}
	}
	if ( !( type & LEFT ) )
		while ( size-- > 0 )
			*str++ = c;
	while ( i < precision-- )
		*str++ = '0';
	while ( i-- > 0 )
		*str++ = tmp[i];
	while ( size-- > 0 )
		*str++ = ' ';
	return str;
}

/* Forward decl. needed for IP address printing stuff... */
int sprintf( char* buf , const char* fmt , ... );

int vsprintf( char* buf , const char* fmt , va_list args )
{
	int len;
	unsigned long num;
	int i, base;
	char* str;
	const char* s;

	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 */

	for ( str = buf ; *fmt ; ++fmt )
	{
		if ( *fmt != '%' )
		{
			*str++ = *fmt;
			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 ( is_digit( *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 ( is_digit( *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' )
		{
			qualifier = *fmt;
			++fmt;
		}

		/* default base */
		base = 10;

		switch ( *fmt )
		{
			case 'c':
				if ( !( flags & LEFT ) )
					while ( --field_width > 0 )
						*str++ = ' ';
				*str++ = ( unsigned char ) va_arg( args , int );
				while ( --field_width > 0 )
					*str++ = ' ';
				continue;

			case 's':
				s = va_arg( args , char * );
				if ( !s )
					s = "<NULL>";

				len = strnlen( s , precision );

				if ( !( flags & LEFT ) )
					while ( len < field_width-- )
						*str++ = ' ';
				for ( i = 0; i < len; ++i )
					*str++ = *s++;
				while ( len < field_width-- )
					*str++ = ' ';
				continue;

			case 'p':
				if ( field_width == -1 )
				{
					field_width = 2 * sizeof( void * );
					flags |= ZEROPAD;
				}
				str = number( str , ( unsigned long ) va_arg( args , void * ) , 16 , field_width , precision , flags );
				continue;


			case 'n':
				if ( qualifier == 'l' )
				{
					long* ip = va_arg( args , long* );
					*ip = ( str - buf );
				}
				else
				{
					int* ip = va_arg( args , int* );
					*ip = ( str - buf );
				}
				continue;

			case '%':
				*str++ = '%';
				continue;

				/* integer number formats - set up the flags and "break" */
			case 'o':
				base = 8;
				break;

			case 'X':
				flags |= LARGE;
			case 'x':
				base = 16;
				break;

			case 'd':
			case 'i':
				flags |= SIGN;
			case 'u':
				break;

			default:
				*str++ = '%';
				if ( *fmt )
					*str++ = *fmt;
				else
					--fmt;
				continue;
		}
		if ( qualifier == 'l' )
			num = va_arg( args , unsigned long );
		else if ( qualifier == 'h' )
		{
			num = ( unsigned short ) va_arg( args , int );
			if ( flags & SIGN )
				num = ( short ) num;
		}
		else if ( flags & SIGN )
			num = va_arg( args , int );
		else
			num = va_arg( args , unsigned int );
		str = number( str , num , base , field_width , precision , flags );
	}
	*str = '\0';
	return str - buf;
}

int sprintf( char* buf , const char* fmt , ... )
{
	va_list args;
	int i;

	va_start( args , fmt );
	i = vsprintf( buf , fmt , args );
	va_end( args );
	return i;
}

/*
void panic(const char *fmt, ...)
{
	va_list	args;
	va_start(args, fmt);
	printf(fmt);
	putc('\n');
	va_end(args);
#if defined (CONFIG_PANIC_HANG)
	hang();
#else
	udelay (100000);	// allow messages to go out
	do_reset (NULL, 0, 0, NULL);
#endif
}*/

⌨️ 快捷键说明

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