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

📄 printf.c

📁 DSP56F807的CAN通讯程序,可用于多子板互连、也可作为开发的原型程序
💻 C
字号:
/* Author: Daniel Malik (daniel.malik@motorola.com) */

/* Revision history:
1.0		First code released (15/02/2001)
1.1		Bug in fractional support: fmtpars.justification_options == zero_fill; changed to: fmtpars.justification_options = zero_fill;
		Changed fractional handling, 0xe000 is -.25 not -.75 as I thought
1.2		Optimized number printout (now uses unsigned division and unsigned parameters), hex printout correction (22/02/2001)
1.3		global variable changed to static (19/03/2001)
*/

#include "stdio.h"

/* options */
#define	support_fractional	/* fractional (16bit), conversion character "r", precision (when >3) specifies maximum number of characters (no rounding is done, string is cut) */

#define	BUFFER_SIZE	15	/* buffer size for number conversion */
#define isdigit(c)	((c>='0')&&(c<='9'))

enum justification_options {
	left_justification,
	right_justification,
	zero_fill
};

enum sign_options {
	only_minus,
	sign_always,
	space_holder
};

enum argument_options {
	normal_argument,
	long_argument
};

typedef struct {
	int	justification_options;
	int	sign_options;
	int	alternate_form;
	int	argument_options;
	int	conversion_char;
	int	field_width;
	int	precision;
} print_format;

char *parseformat(char *format,print_format *f,va_list *arg) {
	int	flag_found;
	char c=*format;
	
	(*f).justification_options	= right_justification;
	(*f).sign_options			= only_minus;
	(*f).alternate_form			= 0;
	(*f).argument_options		= normal_argument;
	(*f).field_width			= 0;
	(*f).precision				= -1;		/* -1 means not specified */
	
	if (c == '\0') return(0);
	if (c == '%') {
		(*f).conversion_char = '%';
		return(++format);
	}
	do {
		flag_found = 1;
		switch (c) {
			case '-':	(*f).justification_options = left_justification; break;
			case '+':	(*f).sign_options = sign_always; break;
			case ' ':	if ((*f).sign_options != sign_always) (*f).sign_options = space_holder; break;
			case '#':	(*f).alternate_form = 1; break;
			case '0':	if ((*f).justification_options != left_justification) (*f).justification_options = zero_fill; break;
			default:	flag_found = 0;
		}
		if (flag_found) c=*++format; else break;
	} while (flag_found);
	if (c == '*') {
		if (((*f).field_width = va_arg(*arg, int)) < 0) {
			(*f).justification_options = left_justification;
			(*f).field_width = -(*f).field_width;
		}
		c = *++format;
	}
	else while (isdigit(c)) {
		(*f).field_width = ((*f).field_width * 10) + (c - '0');
		c = *++format;
	}
	if (c == '.') {
		(*f).precision = 0;
		if ((c = *++format) == '*') {
			if (((*f).precision = va_arg(*arg, int)) < 0) (*f).precision = 0;
			c = *++format;
		}
		else while (isdigit(c))	{
				(*f).precision = ((*f).precision * 10) + (c - '0');
				c = *++format;
			}
	}
	if (c=='l') {
		(*f).argument_options = long_argument;
		c = *++format;
	}
	(*f).conversion_char = c;
	switch (c) {
		case 'd':
		case 'i':
		case 'u':
		case 'o':
		case 'x':
		case 'X':
			if ((*f).precision<0) (*f).precision = 1;
			else if ((*f).justification_options == zero_fill) (*f).justification_options = right_justification;
			break;
		case 'f':
		case 'F':
			if ((*f).precision<0) (*f).precision = 6;
			break;
	    case 'g':
		case 'G':
		case 'e':
		case 'E':
			if ((*f).precision<0) (*f).precision = 6;
			if (!(*f).precision) (*f).precision = 1;
			break;
		case 'p':
			(*f).conversion_char  = 'x';
			(*f).alternate_form   = 1;
			(*f).precision        = 4;
			break;
		case '\0':
			return(0);			
	}
	return(++format);
}

/* returns pointer to first character of output string */
char *long2str (unsigned long int n, char *buffer, print_format *f) {
	int base,minus=0,digit,count=0;
	buffer+=BUFFER_SIZE;		/*maximum length of long number plus sign */
	switch ((*f).conversion_char) {
		case 'd':
#ifdef support_fractional
		case 'r':
#endif
		case 'i':
			if (n & 0x80000000) {
				n=~n+1;
				minus=1;
			}
		case 'u':
			base =  10;
			break;
		case 'o':
			base =   8;
			break;
		case 'x':
		case 'X':
			base =  16;
	}
	do {
		digit=n%base;
		n/=base;
		if (digit<10) digit+='0'; else {
			digit+='a'-10;
			if ((*f).conversion_char=='X') digit+='A'-'a';
		}
		*(--buffer)=digit;
		count++;
	} while (n);
	if (base == 8 && (*f).alternate_form && *(++buffer) != '0') {
		*--buffer = '0';
		count++;
	}
	if ((*f).justification_options == zero_fill) {
		(*f).precision = (*f).field_width;
		if (minus || (*f).sign_options != only_minus) (*f).precision--;
		if (base == 16 && (*f).alternate_form) (*f).precision-=2;
	}
	if ((count<BUFFER_SIZE)&&(count<(*f).precision)) {
		*--buffer='0';
		count++;
	}
	if (base == 16 && (*f).alternate_form) {
		*--buffer = (*f).conversion_char;
		*--buffer = '0';
	}
	if (minus) *--buffer = '-'; 
		else if ((*f).sign_options == sign_always) *--buffer = '+';
			else if ((*f).sign_options == space_holder) *--buffer = ' ';
	return(buffer);
}

void justify_and_print_string(void (*output_func)(char), char *buffer, print_format *f) {
	int buf_lng;
	char *bptr=buffer;
	while(*(bptr++));
	buf_lng=bptr-buffer-1;
	if ((*f).justification_options != left_justification) {
		int i;
		char fill_char = ((*f).justification_options == zero_fill) ? '0' : ' ';
		if (((*buffer == '+') || (*buffer == '-')) && (fill_char == '0')) {
			output_func(*(buffer++));
			buf_lng--;
		}
		i=buf_lng;
		while (i<(*f).field_width) {
			output_func(fill_char);
			i++;
		}
	}
	while(*buffer) output_func(*(buffer++));
	if ((*f).justification_options == left_justification) {
		while (buf_lng < (*f).field_width) {
			output_func(' ');
			buf_lng++;
		}
	}
}

#ifdef support_fractional
unsigned long fractable[15]={500000000,250000000,125000000,62500000,31250000,
							 15625000,7812500,3906250,1953125,976563,488281,
							 244141,122070,61035,30518};
long int frac2long (unsigned long int number) {
	int i;
	long int result=0;
	for (i=14;i>=0;i--) {
		if (number&1) result+=fractable[i];
		number>>=1;
	}
	if (number&1) return(result-(long)1000000000);
	return(result);
}
#endif

void pformatter (void (*output_func)(char), char *format, va_list arg) {
	print_format fmtpars;
	char *fmt1;
	while ((*format)!='\0') {
		while (((*format)!='%')&&((*format)!='\0')) {
			output_func(*(format++));
		}
		fmt1=format;
		if ((*(format))!='\0') if (format = parseformat(format+1,&fmtpars,&arg)) {
			switch (fmtpars.conversion_char)
			{
				case 'c':	output_func(va_arg(arg, char)); break;
				case '%':	output_func('%'); break;
				case 's':	justify_and_print_string(output_func,va_arg(arg,char *),&fmtpars); break;
#ifdef support_fractional
				case 'r':	{
						char buffer[BUFFER_SIZE+1+2];
						char *bptr;
						unsigned long int number;
						int i,j;
						buffer[BUFFER_SIZE+2]='\0';
						if (fmtpars.argument_options == long_argument)	number = va_arg(arg, unsigned long);
							else number = va_arg(arg, unsigned int);
						number=frac2long(number);
						j=fmtpars.precision;
						i=fmtpars.field_width;
						fmtpars.field_width=10;
						fmtpars.justification_options = zero_fill;
						bptr=long2str((unsigned long int)number,buffer+2,&fmtpars);
						if (!isdigit(*bptr)) {
							*(bptr-2)=*bptr;
							*(bptr-1)='0';
							*(bptr)='.';
							bptr-=2;
						} else {
							*(bptr-1)='0';
							*(bptr)='.';
							bptr--;
						}
						fmtpars.field_width=i;
						if ((j<12)&&(j>3)) *(bptr+j)='\0';		/* shorten the string if precision > 3 */
						justify_and_print_string(output_func,bptr,&fmtpars); 
					} break;
#endif
				case 'd':
				case 'o':
				case 'u':
				case 'x':
				case 'X':
				case 'i':	{
						char buffer[BUFFER_SIZE+1];
						char *bptr;
						long int number;
						buffer[BUFFER_SIZE]='\0';
						if (fmtpars.argument_options == long_argument)	number = va_arg(arg, long);
							else if (fmtpars.conversion_char=='d') number = va_arg(arg, int);
								else number = va_arg(arg, unsigned int);
						bptr=long2str((unsigned long int)number,buffer,&fmtpars);
						justify_and_print_string(output_func,bptr,&fmtpars); 
					} break;
				default:	while(fmt1<format) output_func(*(fmt1++));	/* print unknown conversion strings */
			}
		}
	}
}

void printf(char *format, ...) {
	pformatter(&stdio_putchar, format, va_start(format));
}

static char *dest_ptr;

void output_to_string(char character) {
	*(dest_ptr++)=character;
}

void sprintf(char *dest, char *format, ...) {
	char *old_dest_ptr=dest_ptr;		/* save old pointer to make sprintf reentrant */
	dest_ptr=dest;	
	pformatter(&output_to_string, format, va_start(format));
	*dest_ptr='\0';
	dest_ptr=old_dest_ptr;	
}

⌨️ 快捷键说明

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