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

📄 printf.c

📁 HaiBIOS 是为我的S3C2410开发板写的一个启动程序。 C盘是RAMDISK
💻 C
字号:
//---------------------------------------------------------------------------------
// Copyright (c) Haisoft 2006-9-1
// Copyright jinhailiao 2008-2010
// E-mail:   jinhailiao@163.com
// Project:			HGui
// File:			printf.c
// Description:		a simple sprintf() and printf()...
//-------------------------------------------------------------
// Reversion Histroy:
//-------------------------------------------------------------
// Version		date		operations				by who
// 1.0.0		2008-05-30  create                  Kingsea
//---------------------------------------------------------------------------------
#include "haitype.h"
#include "haiclib.h"


#ifdef HAVE_STDARG_H

#include "stdarg.h"

#else

typedef char *  va_list;
#define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
#define va_start(ap,v)  ( ap = (va_list)&v + _INTSIZEOF(v) )
#define va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_end(ap)      ( ap = (va_list)0 )

#endif

double hai_pow(double x, int y)
{
	int i;
	double num = 1.0;
	
	if (y == 0)
		return 1.0;
	for (i = 0; i < y; i++)
		num = num * x;
	return num;
}

void hai_SplitDouble(double val, int precision, double *outd, double *outf)
{
	int num, i, m, ival;
	double fval, dval = 0.0, fdval;

	if (val < 0) val = -val;
	
	for (num=0,fval=val; fval>=1.0; num++,fval/=10.0);
	for (i = 0; i < num; i++)
	{
		ival = (int)(fval*=10.0);
		fval -= (double)ival;
		dval = dval*10.0+ival;//累加整数值
	}
	
	fdval = val - dval;
	for (m=0,fval=fdval; fval>0&&m<precision+1; m++)
	{
		ival = (int)(fval *= 10.0);
		fval -= (double)ival; 
	}
	if (m > precision)
	{
		fval = hai_pow(10, precision);
		fval = 0.5/fval;
		fdval += fval;
		if (fdval >= 1.0)
		{
			fdval -= 1.0;
			dval  += 1.0;
		}
	}
	*outd = dval;
	*outf = fdval;
}

enum {SP_START, SP_FLAG, SP_WIDTH, SP_PRECI, SP_TYPE, SP_END};
#define SP_ALIGN_LEFT	1
#define SP_ALIGN_RIGHT	0
#define SP_SIGN_YES		1
#define SP_SIGN_NO		0

S_WORD hai_vsprintf(char *buf, const char *format, va_list argptr)
{
	char ch;
	char *p = buf;
	char *pHex = "0123456789ABCDEF";//HexUp
	char *HexLo = "0123456789abcdef";
	char NumStr[256];
	int  i, val;
	va_list va = argptr;

	while (*format)
	{
		if (*format == '%')
		{
			char state = SP_START;
			char prefix = 1;
			char fill = ' ';
			char NeedFill = 0;
			char sign = SP_SIGN_NO;
			char HexOct = 0;
			char align = SP_ALIGN_RIGHT;
			char *pstr;
			int  width = 0;
			int  precision = -1;
			int  ival = 0;
			double fval = 0.0, dval = 0.0, fdval = 0.0;
			unsigned int uval = 0;

			format++;
			while (ch=*format)
			{
				switch (state)
				{
				case SP_START:
					if (ch=='-'||ch=='+'||ch==' '||ch=='0'||ch=='#')//flag
						state = SP_FLAG;
					else if (ch>='1' && ch<='9')
						state = SP_WIDTH;
					else if (ch == '.')
						state = SP_PRECI, precision = 0, format++ /* skip the '.' */;
					else if (ch=='c'||ch=='C'||ch=='d'||ch=='i'||ch=='o'||ch=='u'||ch=='x'||ch=='X'||ch=='e'||ch=='E'
									||ch=='f'||ch=='g'||ch=='G'||ch=='n'||ch=='P'||ch=='s'||ch=='S')
						state = SP_TYPE;
					else
						state = SP_END;
					break;

				case SP_FLAG:
					format++;
					if (ch=='-')
						align = SP_ALIGN_LEFT;
					else if (ch=='+')
						sign = SP_SIGN_YES;
					else if (ch==' '||ch=='0')
						fill = ch, NeedFill = 1;
					else if (ch=='#')
						HexOct = 1;
					else
						state = SP_START, format-- /* back one char */;
					break;

				case SP_WIDTH:
					if (ch>='0' && ch<='9')
						format++, width = width*10 + (ch-'0');
					else if (ch == '.')
						state = SP_PRECI, precision = 0, format++ /* skip the '.' */;
					else if (ch=='c'||ch=='C'||ch=='d'||ch=='i'||ch=='o'||ch=='u'||ch=='x'||ch=='X'||ch=='e'||ch=='E'
									||ch=='f'||ch=='g'||ch=='G'||ch=='n'||ch=='P'||ch=='s'||ch=='S')
						state = SP_TYPE;
					else
						state = SP_END;
					break;

				case SP_PRECI:
					if (ch>='0' && ch<='9')
						format++, precision = precision*10 + (ch-'0');
					else if (ch=='c'||ch=='C'||ch=='d'||ch=='i'||ch=='o'||ch=='u'||ch=='x'||ch=='X'||ch=='e'||ch=='E'
									||ch=='f'||ch=='g'||ch=='G'||ch=='n'||ch=='P'||ch=='s'||ch=='S')
						state = SP_TYPE;
					else
						state = SP_END;
					break;

				case SP_TYPE:
					switch (ch)
					{
					case 'c':
					case 'C':
						ival = va_arg(va, char);
						if (align==SP_ALIGN_RIGHT)
							while (width-- > 1) *p++ = fill;
						*p++ = (char)ival;
						if (align==SP_ALIGN_LEFT)
							while (width-- > 1) *p++ = fill;
						break;
					case 'd':
					case 'i':
						ival = va_arg(va, int);
						if (precision == -1) precision = 1;
						for (i=0, val=ival<0? -ival:ival; val>0; i++, val = val/10)
							NumStr[i] = val%10+'0';
						for (; i < precision; i++)
							NumStr[i] = '0';
//						if (i==0) NumStr[i++] = '0';
						val = i;
						if (align==SP_ALIGN_LEFT)
						{
							if (ival<0 || sign==SP_SIGN_YES)
								*p++ = ival<0? '-':'+';
							else if (NeedFill==1 && fill==' ')
								*p++ = fill;
							else
								prefix = 0; // set NO_PRE_FILL flag
							for (i--; i >= 0; i--) 
								*p++ = NumStr[i];
							for (width -= (prefix+val); width > 0; width--)
								*p++ = ' ';
						}
						else
						{
							if (width <= val)
							{
								if (ival<0 || sign==SP_SIGN_YES)
									*p++ = ival<0? '-':'+';
								else if (NeedFill==1 && fill==' ')
									*p++ = fill;
							}
							else
							{
								if (!(ival<0 || sign==SP_SIGN_YES))
									prefix = 0;
								if (fill==' ')
								{
									for (width -= (prefix+val); width > 0; width--)
										*p++ = fill;
									if (prefix) *p++ = ival<0? '-':'+';
								}
								else
								{
									if (prefix) *p++ = ival<0? '-':'+';
									for (width -= (prefix+val); width > 0; width--)
										*p++ = fill;
								}
							}
							for (i--; i >= 0; i--) 
								*p++ = NumStr[i];
						}
						break;
					case 'u':
						uval = va_arg(va, unsigned int);
						if (precision == -1) precision = 1;
						for (i=0; uval>0; i++, uval = uval/10)
							NumStr[i] = uval%10+'0';
						for (; i < precision; i++)
							NumStr[i] = '0';
//						if (i==0) NumStr[i++] = '0';
						val = i;
						if (align==SP_ALIGN_LEFT)
						{
							for (i--; i >= 0; i--) 
								*p++ = NumStr[i];
							for (width -= val; width > 0; width--)
								*p++ = ' ';
						}
						else
						{
							for (width -= val; width > 0; width--)
								*p++ = fill;
							for (i--; i >= 0; i--) 
								*p++ = NumStr[i];
						}
						break;
					case 'o':
						uval = va_arg(va, unsigned int);
						if (precision == -1) precision = 1;
						for (i=0; uval>0; i++, uval = uval>>3)
							NumStr[i] = (uval&0x7)+'0';
						for (; i < precision; i++)
							NumStr[i] = '0';
//						if (i==0) NumStr[i++] = '0';
						val = i;
						if (align==SP_ALIGN_LEFT)
						{
							if (HexOct) *p++ = '0';
							else prefix = 0;
							for (i--; i >= 0; i--) 
								*p++ = NumStr[i];
							for (width -= (prefix+val); width > 0; width--)
								*p++ = ' ';
						}
						else
						{
							if (!HexOct) prefix = 0;
							for (width -= (prefix+val); width > 0; width--)
								*p++ = fill;
							if (HexOct) *p++ = '0';
							for (i--; i >= 0; i--) 
								*p++ = NumStr[i];
						}
						break;
					case 'x':
						pHex = HexLo; //default -> HexUp;
					case 'X':
						uval = va_arg(va, unsigned int);
						if (precision == -1) precision = 1;
						for (i=0; uval>0; i++, uval = uval>>4)
							NumStr[i] = pHex[uval&0xF];
						for (; i < precision; i++)
							NumStr[i] = '0';
//						if (i==0) NumStr[i++] = '0';
						val = i;
						if (align==SP_ALIGN_LEFT)
						{
							if (HexOct) *p++ = '0', *p++ = 'x', prefix = 2;
							else prefix = 0;
							for (i--; i >= 0; i--) 
								*p++ = NumStr[i];
							for (width -= (prefix+val); width > 0; width--)
								*p++ = ' ';
						}
						else
						{
							if (HexOct) prefix = 2;
							else prefix = 0;
							if (fill == ' ')
							{
								for (width -= (prefix+val); width > 0; width--)
									*p++ = fill;
								if (HexOct) *p++ = '0', *p++ = 'x';
							}
							else
							{
								if (HexOct) *p++ = '0', *p++ = 'x';
								for (width -= (prefix+val); width > 0; width--)
									*p++ = fill;
							}
							for (i--; i >= 0; i--) 
								*p++ = NumStr[i];
						}
						break;
					case 's':
					case 'S':
						pstr = va_arg(va, char*);
						if (!pstr) pstr = "<null>";
						for (i = 0; pstr[i]; i++);
						val = i;
						if (align == SP_ALIGN_LEFT)
						{
							for (i = 0; i < val; i++) 
								*p++ = pstr[i];
							for (width -= val; width > 0; width--)
								*p++ = ' ';
						}
						else
						{
							for (width -= val; width > 0; width--)
								*p++ = fill;
							for (i = 0; i < val; i++) 
								*p++ = pstr[i];
						}
						break;
					case 'f':
						dval = va_arg(va, double);
						if (precision == -1) precision = 6;
						hai_SplitDouble(dval, precision, &fval, &fdval);
						for (val=0; fval>=1.0; val++,fval/=10.0);
						for (i = 0; i < val; i++)
						{
							ival = (int)(fval*=10.0);
							NumStr[i] = (char)ival+'0';
							fval -= (double)ival;
						}						
						if (val==0) NumStr[val++] = '0';

						if (align==SP_ALIGN_LEFT)
						{
							if (dval<0 || sign==SP_SIGN_YES)
								*p++ = dval<0? '-':'+';
							else if (NeedFill==1 && fill==' ')
								*p++ = fill;
							else
								prefix = 0; // set NO_PRE_FILL flag
							for (i = 0; i < val; i++) 
								*p++ = NumStr[i];
							*p++ = '.';

							for (i = 0; i < precision; i++)
							{
								ival = (int)(fdval *= 10.0);
								*p++ = (char)ival + '0';
								fdval -= (double)ival;
							}
							for (width -= (prefix+val+precision+1); width > 0; width--)//add 1 for the '.'
								*p++ = ' ';
						}
						else
						{
							if (width <= (val+precision+1))
							{
								if (dval<0 || sign==SP_SIGN_YES)
									*p++ = dval<0? '-':'+';
								else if (NeedFill==1 && fill==' ')
									*p++ = fill;
							}
							else
							{
								if (!(dval<0 || sign==SP_SIGN_YES))
									prefix = 0;
								if (fill==' ')
								{
									for (width -= (prefix+val+precision+1); width > 0; width--)
										*p++ = fill;
									if (prefix) *p++ = dval<0? '-':'+';
								}
								else
								{
									if (prefix) *p++ = dval<0? '-':'+';
									for (width -= (prefix+val+precision+1); width > 0; width--)
										*p++ = fill;
								}
							}
							for (i = 0; i < val; i++) 
								*p++ = NumStr[i];
							*p++ = '.';
							for (i = 0; i < precision; i++)
							{
								ival = (int)(fdval *= 10.0);
								*p++ = (char)ival + '0';
								fdval -= (double)ival;
							}
						}
						break;
					case 'e':
					case 'E':
					case 'g':
					case 'G':
					case 'n':
					case 'P'://unsupport now......
						dval = va_arg(va, double);
						break;
					default:
						break;
					}
					format++, state = SP_END;
					break;

				default:
					break;
				}
				if (state == SP_END)
					break;
			}
		}
#if 0
		else if (*format == '\\') //process escape sequences
		{
			switch (*++format)
			{
			default : *p++ = *format++; break;
			case 'a': *p++ = '\a'; format++; break; // Bell (alert)
			case 'b': *p++ = '\b'; format++; break; // Backspace 
			case 'f': *p++ = '\f'; format++; break; // Formfeed 
			case 'n': *p++ = '\n'; format++; break; // New line 
			case 'r': *p++ = '\r'; format++; break; // Carriage return 
			case 't': *p++ = '\t'; format++; break; // Horizontal tab 
			case 'v': *p++ = '\v'; format++; break; // Vertical tab 
			// user default \' Single quotation mark 
			// user default \"  Double quotation mark 
			// user default \\ Backslash 
			// user default \? Literal question mark 
			case '0': case '1': case '2': case '3':// \ooo ASCII character in octal notation 
			case '4': case '5': case '6': case '7':
				for (val=*format-'0',ch=*++format,i=0; (ch>='0'&&ch<='7')&&(i<2); ch=*++format,i++)
					val = val*8+(ch-'0');
				*p++ = val;
				break;
			case 'x': // \xhhh ASCII character in hexadecimal notation
				for (ch = *++format,val = 0,i = 0; i < 2; ch = *++format,i++)
					if (ch>='0'&&ch<='9') val = val*16 + (ch-'0');
					else if (ch>='a'&&ch<='f') val = val*16 + (ch-'a'+10);
					else if (ch>='A'&&ch<='F') val = val*16 + (ch-'A'+10);
					else break;
				if (val == 0 && i == 0) val = 'x';
				*p++ = val;
				break;
			}
		}
#endif
		else
		{
			*p++ = *format++;
		}
	}

	va_end(va);
	*p = '\0';

	return (S_WORD)(p-buf);
}

S_VOID hai_PutChar(char ch)
{
	//user add code for yourself purpose
	void hai_UartPutChar(S_BYTE data);
	hai_UartPutChar(ch);
}

S_WORD hai_sprintf(char *buf, const char *format, ...)
{
	S_WORD num;
	va_list va;

	va_start(va, format);
	num = hai_vsprintf(buf, format, va);
	va_end(va);

	return num;	
}

S_WORD hai_printf(const char *format, ...)
{
	S_WORD num;
	va_list va;
	char buf[1024], *p = buf;

	hai_memset(buf, 0x00, sizeof(buf));
	va_start(va, format);
	num = hai_vsprintf(buf, format, va);
	va_end(va);

	while (*p)
		hai_PutChar(*p++);

	return num;	
}

⌨️ 快捷键说明

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