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

📄 _doprint.c

📁 一个分选系统的软件:用SmallRtos操作系统
💻 C
字号:
/*
 *	@(#)_doprint.c	1.15
 */

/**************************************************************************
**                                                                        *
**  FILE        :  _doprint.c                                             *
**                                                                        *
**  DESCRIPTION :  Source file for _doprint() routine                     *
**                 This routine is used to create all different           *
**                 formatting routines for _printf().                     *
**                 when SMALL is defined, a version without floating      *
**                 point is created, and no length specifiers, etc. are   *
**                 supported.                                             *
**                 when MEDIUM is defined, a version without floating     *
**                 point is created.                                      *
**                 Default, an ANSI version is created.                   *
**                                                                        *
**  NOTE	:  One thing in this formatter (specially designed for	  *
**		   C166) is the printing of pointer values		  *
**		   '%p' will print a 'default' pointer (ANSI)		  *
**		   '%hp' will always print a 'near' pointer		  *
**		   '%lp' will always print a 'far' pointer		  *
**		   '%Lp' will always print a 'huge' pointer		  *
**                                                                        *
**		   Define :                                               *
**		   SMALL  - No floats, no length specifiers (default)     *
**                 MEDIUM - No floats                                     *
**                 LARGE  - Full ANSI formatter                           *
**                                                                        *
**  COPYRIGHT   :  1995 Tasking Software B.V.                             *
**                                                                        *
**************************************************************************/

#include <stdarg.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <string.h>

#if !defined SMALL && !defined MEDIUM && !defined LARGE
#define	SMALL		/* Default formatter */
#endif

/* Print a string (without newline) */
static void _fputs( char *str, FILE *fout, unsigned int *characters );

/* convert an unsigned int to a string			*/
extern char * _ltoa( char *p, unsigned long num, unsigned char radix );

/* Print a character in hexadecimal format */
static void _printhex( unsigned char c, FILE *fout, unsigned int *characters );

#ifndef SMALL
static void _putstring( unsigned char format, int min, int max,
			char *str, FILE *fout, unsigned int *characters );
static void _putnumber( int min, int max, unsigned char ch, unsigned char format,
			void *pvalue, FILE *fout, unsigned int *characters );
#else
#define	_putstring( x, y, z )	_fputs( x, y, z )
static void _putnumber( unsigned char ch, unsigned char format,
			void *pvalue, FILE *fout, unsigned int *characters );
#endif

/* Print one character in hexadecimal format */
static void
_printhex( unsigned char c, FILE *fout, unsigned int *characters )
{
	unsigned char cha;

	*characters += 2;
	cha = (c >> 4) & 0x0F;
	cha += cha > 9 ? 'A'-10 : '0';
	fputc( cha, fout );
	cha = c & 0x0F;
	cha += cha > 9 ? 'A'-10 : '0';
	fputc( cha, fout );
}

/* Floating point formatter */
#ifdef	LARGE
extern void	_doflt( int min, int max, unsigned char ch, unsigned char format,
			double *pvalue, FILE *fout, unsigned int *characters );
#endif

/* does the actual printing	*/
int
_doprint( register const char *fmt, va_list ap, FILE *fout )
{

#ifndef SMALL
	register int min;		/* minimum length of output field */
	register int max;		/* maximum length of output field */
#endif

	register unsigned char ch;	/* character in format string	  */
	register unsigned char format;	/* b7 - zero fill float		  */
	                                /* b6 - left alignment		  */
					/* b5 - zero fill		  */
					/* b4 - alternate print		  */
					/* b3,b2 - 0x04 --> always sign	  */
					/*       - 0x08 --> sign or space */
					/* b1,b0 - 0x01 --> short	  */
					/*       - 0x02 --> long	  */
					/*       - 0x03 --> double	  */
	unsigned char mxflg = 0;	/* Flag if a maximum length */
					/* specifier is found */

	unsigned int characters = 0;	/* no characters written yet	  */

	for( ;; )
	{
		ch = *fmt++;
		if( !ch )
		{
			return( characters );
		}
		else if( ch == '%' )
		{
			if( *fmt != '%' )
				goto nxt;
			fmt++;
		}
		characters++;
		fputc( ch, fout );
		continue;

		nxt:

#ifndef SMALL
		format = min = max = 0;
#else
		format = 0;
#endif

#ifndef SMALL
		while( 1 )
		{
			ch = *fmt++;
			if( ch == '-' )
				format |= 0x40;	/* left alignment */
			else if( ch == '+' )
				format = (format & 0xF3) | 0x04;
			else if( ch == ' ' )
			{
				/* do not overrule '+'	*/
				if( !(format & 0x0C) )
					format |= 0x08;	/* sign or space */
			}
			else if( ch == '0' )
				format |= 0xA0;	/* zero fill */
			else if( ch == '#' )
				format |= 0x10;	/* alternate print */
			else
				break;
		}

		if( ch == '*' )
		{	/* next argument is minimum field width specifier */
			min = va_arg( ap, int );
			if( min < 0 )
			{
				format |= 0x40;
				min = -min;
			}
			ch = *fmt++;
		}
		else
		{
			while( ch >= '0' && ch <= '9' )
			{	/* get minimum field width */
				min = min * 10 + ch - '0';
				ch = *fmt++;
			}
		}
		if( ch == '.' )
		{	/* next argument is maximum field width specifier */
			format &= ~0x20;	/* zero fill must be disabled */
			mxflg = 1;		/* read a value for 'max' */
			if( (ch = *fmt++) == '*' )
			{
				max = va_arg( ap, int );
				if( max < 0 )
				{
					format |= 0x40;
					max = -max;
				}
				ch = *fmt++;
			}
			else
			{
				while( ch >= '0' && ch <= '9' )
				{	/* get maximum field width */
					max = max * 10 + ch - '0';
					ch = *fmt++;
				}
			}
		}
#else
		ch = *fmt++;
#endif

		do
		{
			if( ch == 'l' )
			{
				format |= 0x02;
			}
			else if( ch == 'h' )
			{
				format |= 0x01;
			}
			else if( ch == 'L' )
			{
				format |= 0x03;
			}
			else
				continue;

			ch = *fmt++;
		} while( 0 );

		if( ch == 'c' || ch == 'd' || ch == 'i' || ch == 'o' ||
		    ch == 'x' || ch == 'X' || ch == 'u' )
		{
			/* character			*/
			/* signed decimal integer	*/
			/* unsigned octal int		*/
			/* unsigned hexadecimal int	*/
			/* unsigned decimal int		*/
			/* int, single character	*/
#ifndef SMALL
			_putnumber( min, max, ch, format,
				    (format & 0x03) == 0x02 ?
					(void *)&va_arg( ap, long ) :
					(void *)&va_arg( ap, int ),
				    fout, &characters );
#else
			_putnumber( ch, format,
				    (format & 0x03) == 0x02 ?
					(void *)&va_arg( ap, long ) :
					(void *)&va_arg( ap, int ),
				    fout, &characters );
#endif
		}
		else if( ch == 's' )
		{
			/* string */
#ifndef SMALL
			_putstring(	format, min, max, va_arg( ap, char * ),
					fout, &characters );
#else
			_putstring(	va_arg( ap, char * ), fout, &characters );
#endif
		}

		else if( ch == 'f' || ch == 'e' || ch == 'E' ||
			 ch == 'g' || ch == 'G' )
		{
			/* floating point	*/
#ifdef LARGE		/* Only supported on 'LARGE' formatter */
			if( format & 0x80 )
			{
				format &= 0x7F;
				format |= 0x20;
			}
			if( !mxflg )
				max = 6;
			_doflt(	min, max, ch, format, (double *)&va_arg( ap, double ), 
				fout, &characters );
#else
			/* Just print we do not support floating point values */
			_fputs( "<no floats>", fout, &characters );
			/* select next argument	*/
			va_arg( ap, double );	
#endif
		}

		else if( ch == 'p' )
		{
#if _MODEL == 't' || _MODEL == 's'
			/* In tiny or small model, a near pointer	*/
			/* Print as '<near>%04X'			*/
			if ( !(format & 0x03) )
			{
				format |= 0x1;	/* Near pointer */
			}
#else	/* _MODEL == 'm' || _MODEL == 'l' */
			/* In Medium and Large model, always a far pointer */
			/* Print as '<far>%02X:%04X'	*/
			if ( !(format & 0x03) )
			{
				format |= 0x2;	/* Far pointer */
			}
#endif
			/* At this point, (format & 0x03) represents : 	*/
			/*	0x01 -> Near pointer (%p or %hp)	*/
			/*	0x02 -> Far pointer  (%p or %lp)	*/
			/*	0x03 -> Huge pointer (%Lp)		*/

#ifndef	SMALL
			/* misuse 'max' */
			max = (format & 0x03) == 0x01 ? 10 : (format & 0x03) == 0x02 ? 14 : 13;

			if( !(format & 0x40) )
			{	/* right alignment ?	*/
				for( ; min>max; --min )
				{
					characters++;
					fputc( ' ', fout );
				}
			}
#endif
			_fputs( (format & 0x03) == 0x01 ? "<near>" :
				(format & 0x03) == 0x02 ? "<far>" :
							  "<huge>", 
				fout, &characters
			      );
			{
				unsigned char cc;
				/* <near>XXXX, <far>XXXX:XXXX, <huge>XX:XXXX */
				if ( (format & 0x03) != 0x01 )
				{
#ifdef FIX_BFWD
#pragma fix_byte_write
#endif
					for( cc = ((format & 0x03) == 0x03 ? 3 : 4);
					     cc-- > 2;
					   )
					{	/* (far) cc = 3, cc = 2 */
						_printhex( (*(char **)ap)[cc],
							   fout, &characters );
					}
#ifdef FIX_BFWD
#pragma nofix_byte_write
#endif

					characters++;
					fputc( ':', fout );
				}

				for( cc = 2; cc-- != 0; )
				{	/* cc = 1, cc = 0 */
					_printhex( (*(char **)ap)[cc], fout, &characters );
				};
			}
#ifndef	SMALL
			for( ; min>max; --min )
			{
				characters++;
				fputc( ' ', fout );
			}
#endif

#if _MODEL == 't'
			va_arg( ap, void * );	/* select next argument	*/
#else
			if( (format & 0x03) == 0x01 )
				va_arg( ap, near void * );
			else if( (format & 0x03) == 0x02 )
				va_arg( ap, far void * );
			else
				va_arg( ap, huge void * );
#endif
		}

		else if( ch == 'n' )
		{
			*(va_arg( ap, int * )) = characters;
		}
		else
		{
			errno = ERR_FORMAT;	/* illegal format string */
			return( characters );
		}
	}
}

/* prints a string to the output					  */
/* when 'min' > 'max', the result is undefined				  */
/* when 'left' != 0, left alignment is done				  */
/* when min=0, and max=0, strings are printed normal			  */
/* length of the strings are supposed to be SMALLer than 30000 characters */
#ifndef SMALL	/* For 'SMALL', _fputs() is called instead of _putstring  */
static void
_putstring(	unsigned char format, register int min, register int max,
		register char *str, FILE *fout, unsigned int *characters )
{
	register int length = 0;

	if( !max )
		max = 30000;

	length = strlen( str );

	if( !(format & 0x40) )		/* right alignment ? */
	{
		for( ; min>length || min>max; --min )
		{
			(*characters)++;
			fputc( ' ', fout );
		}
	}

	while( max-- && *str )		/* print string	*/
	{
		(*characters)++;
		fputc( *str++, fout );
		if( min )
			min--;	/* min will contain the minimum number	*/
				/* of characters to print afterwards	*/
	}

	while( min-- )
	{
		(*characters)++;
		fputc( ' ', fout );		/* padding spaces */
	};
}
#endif	/* SMALL */

static void
#ifndef SMALL
_putnumber(	int min, int max, unsigned char ch, unsigned char format,
		void *pvalue, FILE *fout, unsigned int *characters )
#else
_putnumber(	unsigned char ch, unsigned char format, void *pvalue,
		FILE *fout, unsigned int *characters )
#endif
{
	char buf[13];	/* room to print long value in	*/
	register char *buffer;	/* help variable	*/

	register long value = 0;

#ifndef SMALL
	register char length=0;	/* length needed to print value	*/
#endif

	register unsigned char vsign;	/* sign of the value	*/

	if( !(format & 0x02) )		/* 'h' or default, same as -->	*/
					/* (!(format & 0x03) ||		*/
					/* (format & 0x03) == 0x01)	*/
	{	/* short value is the same as int	*/
		value = *(int *)pvalue;
		if( ch != 'd' && ch != 'i' )	/* not a signed integer ? */
			value &= 0xffff;	/* truncate to positive   */
						/* integer */
	}
	else if( (format & 0x03) == 0x02 )	/* 'l'	*/
	{
		value = *(long *)pvalue;
	}
	;

	vsign = 0;	/* 0 - positive value, otherwise negative value */

	if( ch == 'c' )
	{
		buf[0] = value;
		buf[1] = '\0';
	}
	else if( ch == 'd' || ch == 'i' )
	{
		if( value < 0 )
		{
			vsign = '-';
			value = -value;
		}
		goto unsignedint;
	}
	else if( ch == 'u' )
	{
		unsignedint:

		_ltoa( buf, value, 10 );	/* convert to ascii	*/

#ifndef SMALL
		length = strlen( buf );

		if( !vsign )
		{
			if( (format & 0x0C) == 0x04 )	/* sign always	*/
				vsign = '+';
			else if( (format & 0x0C) == 0x08 ) /* sign or space */
				vsign = ' ';
		}

		if( vsign )
		{
			if( min )
				--min;
		}

		if( vsign && (format & 0x60) )	/* ( (format & 0x20) || */
		{				/* (format & 0x40) )	*/
			(*characters)++;
			fputc( vsign, fout );
			vsign = 0;
		}

		if( !(format & 0x40) )	/* right alignment ? */
		{
			while( (min > max) && (min > length) )
			{
				(*characters)++;
				fputc( (format & 0x20) ? '0' : ' ', fout );
				min--;
			}
		}

#endif

		if( vsign )
		{
			(*characters)++;
			fputc( vsign, fout );
		}

#ifndef	SMALL
		while( max-- > length )
		{
			(*characters)++;
			fputc( '0', fout );
			if( min )
				min--;
		}
#endif
	}
	else if( ch == 'o' || ch == 'x' || ch == 'X' )
	{

		_ltoa( buf, value, ch == 'o' ? 8 : 16 );

		if( ch == 'x' )
		{
			/* convert string to lowercase	*/
			for( buffer = buf; *buffer; ++buffer )
			{	/* do not use 'tolower' */
				if( *buffer >= 'A' && *buffer <= 'Z' )
					*buffer += 'a' - 'A';
			}
		}

#ifndef SMALL
		length = strlen( buf );

		if( ! value )
			format &= 0xEF;	/* clear alternate when value is '0' */

		if( (format & 0x10) )	/* alternate */
		{
			if( format & 0x20 )	/* alternate and filling from */
			{			/* the left with zeros	*/
				if( ch != 'o' )
				{
					*characters += 2;
					fputc( '0', fout );	/* leading 0 */
					fputc( ch, fout );
				}
				format &= 0xEF;	/* clear alternate */
			}

			if( ch == 'o' )
			{
				if( max )
					max++;
				if( max <= length )
					max = length+1;
			}
		}

		if( !(format & 0x40) )		/* right alignment	*/
		{
			while( (min > max) && (min > length) )
			{
				(*characters)++;
				fputc( (format & 0x20) ? '0' : ' ', fout );
				min--;
			}
		}

		if( (format & 0x10) && (ch != 'o') )
		{
			*characters += 2;
			fputc( '0', fout );	/* leading 0 */
			fputc( ch, fout );	/* and 'x' */
		}

		while( max-- > length )
		{
			(*characters)++;
			fputc( '0', fout );
			if( min )
				min--;
		}
#endif
	}

#ifndef SMALL
	/* now print the ascii value, padded with spaces */
	_putstring( format, min, 0, buf, fout, characters );
#else
	/* now print the ascii value	*/
	_putstring( buf, fout, characters );
#endif
}

/* print only a string to the output					*/
/* When the 'SMALL' formatter is requested, _fputs() is called for	*/
/* _printstring()							*/
static void
_fputs( char * str, FILE * fout, unsigned int *characters )
{
	while( *str )
	{
		(*characters)++;
		fputc( *str, fout );
		str++;
	}
}

⌨️ 快捷键说明

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