Xinu7/src/cmd/download/lsi11/eload/lib/printf.c

Compare this file to the similar file:
Show the results in this format:

/* printf.c - printf, putc */

/***STANDALONE VERSION  -- If the CSR address is wrong, it is likely	*/
/*				that this will bomb at location 2	*/

#define	CSR	0177560		/* CONSOLE CSR address			*/
#define	READY	0200		/* Device ready bit			*/

struct	csr	{		/* device csr layout			*/
	int	crstat;		/* read csr and buffer			*/
	int	crbuf;
	int	ctstat;		/* transmitter csr and buffer		*/
	int	ctbuf;
};

/*----------------------------------------------------------------------
 *  printf  --  unbuffered output to CONSOLE
 *----------------------------------------------------------------------
 */
printf(fmt, args)
        char *fmt;
{
        int     putc();

        doprnt(fmt, &args, putc, 0);
}

/*----------------------------------------------------------------------
 *  putc  --  write a character on the console using unbuffered I/O
 *----------------------------------------------------------------------
 */
static	putc(junk,c)
	int	junk;
	char	c;
{
	struct csr *csrptr;
	int i;

	if ( c == '\0' )
		return;
	if ( c == '\n' )
		putc(junk,'\r');
	csrptr = (struct csr *)CSR;

	/*NOTE: the LSI can pump characters faster than most other	*/
	/* systems can handle them... This code slows down the effective*/
	/* baud rate so none are lost.  It is NECESSARY to do so when	*/
	/* talking to UNIX, or the VAX just jumbles the bits		*/
	/* Putting it outside the loop means that we spin the wheels	*/
	/* before testing for device busy, but it's still a lousy way	*/
	/* to handle the problem.					*/

	for (i=0; i<900 ; i++) ;

	while ( (csrptr->ctstat & READY) == 0 ) ;	/* poll for idle*/
	csrptr->ctbuf = c;
	while ( (csrptr->ctstat & READY) == 0 ) ;	/* poll for idle*/
}

#define	MAXSTR	80

/*----------------------------------------------------------------------
 *  doprnt --  format and write output using 'func' to write characters
 *----------------------------------------------------------------------
 */
doprnt(fmt, args, func, farg)	/* Steve Salisbury, Purdue University	*/
	char	*fmt;		/* Format string for printf		*/
	int	*args;		/* Arguments to	printf			*/
	int	(*func)();	/* Function to put a character		*/
	int	farg;		/* Argument to func			*/
{
	char	c;
	int	i;
	char	f;		/* The format character	(comes after %)	*/
	char	*str;		/* Running pointer in string		*/
	char	string[20];	/* The string str points to this output	*/
				/*  from number conversion		*/
	int	length;		/* Length of string "str"		*/
	char	fill;		/* Fill	character (' ' or '0')		*/
	int	leftjust;	/* 0 = right-justified,	else left-just.	*/
	int	longflag;	/* != 0	for long numerics - not	used	*/
	int	fmax,fmin;	/* Field specifications	% MIN .	MAX s	*/
	int	leading;	/* No. of leading/trailing fill	chars.	*/
	char	sign;		/* Set to '-' for negative decimals	*/
	char	digit1;		/* Offset to add to first numeric digit	*/

	for(;;) {
		/* Echo characters until '%' or end of fmt string */
		while( (c = *fmt++) != '%' ) {
			if( c == '\0' )
				return;
			(*func)(farg,c);
		}
		/* Echo "...%%..." as '%' */
		if( *fmt == '%' ) {
			(*func)(farg,*fmt++);
			continue;
		}
		/* Check for "%-..." == Left-justified output */
		if (leftjust = ((*fmt=='-') ? 1 : 0) )
			fmt++;
		/* Allow for zero-filled numeric outputs ("%0...") */
		fill = (*fmt=='0') ? *fmt++ : ' ';
		/* Allow for minimum field width specifier for %d,u,x,o,c,s*/
		/* Also allow %* for variable width (%0* as well)	*/
		fmin = 0;
		if( *fmt == '*' ) {
			fmin = *args++;
			++fmt;
		}
		else while( '0' <= *fmt && *fmt <= '9' ) {
			fmin = fmin * 10 + *fmt++ - '0';
		}
		/* Allow for maximum string width for %s */
		fmax = 0;
		if( *fmt == '.' ) {
			if( *(++fmt) == '*' ) {
				fmax = *args++;
				++fmt;
			}
		else while( '0' <= *fmt && *fmt <= '9' ) {
			fmax = fmax * 10 + *fmt++ - '0';
			}
		}
		/* Check for the 'l' option to force long numeric */
		if( longflag = ((*fmt == 'l') ? 1 : 0) )
			fmt++;
		str = string;
		if( (f= *fmt++) == '\0' ) {
			(*func)(farg,'%');
			return;
		}
		sign = '\0';	/* sign == '-' for negative decimal */

		switch( f ) {
		    case 'c' :
			string[0] = (char) *args;
			string[1] = '\0';
			fmax = 0;
			fill = ' ';
			break;

		    case 's' :
			str = (char *) *args;
			fill = ' ';
			break;

		    case 'D' :
			longflag++;
		    case 'd' :
			if ( *args < 0 ) {
				sign = '-';
				if(longflag == 0)
					*args = -*args;
				else
					*(long *)args = -*(long *)args;
			}
			longflag--;

		    case 'U':
			longflag++;
		    case 'u':
			if( longflag ) {
				digit1 = '\0';
				/* "negative" longs in unsigned format	*/
				/* can't be computed with long division	*/
				/* convert *args to "positive", digit1	*/
				/* = how much to add back afterwards	*/
				while(*(long *)args < 0) {
					*(long *)args -= 1000000000L;
					++digit1;
				}
				_prtl10(*(long *)args, str);
				str[0] += digit1;
				++args;
			} else
				_prt10(*args, str);
			fmax = 0;
			break;

		    case 'O' :
			longflag++;
		    case 'o' :
			if ( longflag ) {
				_prtl8(*(long *)args, str);
				++args;
			} else
				_prt8(*args, str);
			fmax = 0;
			break;

		    case 'X' :
			longflag++;
		    case 'x' :
			if( longflag ) {
				_prtl16(*(long *)args, str);
				++args;
			} else
				_prt16(*args, str);
			fmax = 0;
			break;

		    default :
			(*func)(farg,f);
			break;
		}
		args++;
		for(length = 0; str[length] != '\0'; length++)
			;
		if ( fmin > MAXSTR || fmin < 0 )
			fmin = 0;
		if ( fmax > MAXSTR || fmax < 0 )
			fmax = 0;
		leading = 0;
		if ( fmax != 0 || fmin != 0 ) {
			if ( fmax != 0 )
				if ( length > fmax )
					length = fmax;
			if ( fmin != 0 )
				leading = fmin - length;
			if ( sign == '-' )
				--leading;
		}
		if( sign == '-' && fill == '0' )
			(*func)(farg,sign);
		if( leftjust == 0 )
			for( i = 0; i < leading; i++ )
				(*func)(farg,fill);
		if( sign == '-' && fill == ' ' )
			(*func)(farg,sign);
		for( i = 0 ; i < length ; i++ )
			(*func)(farg,str[i]);
		if ( leftjust != 0 )
			for( i = 0; i < leading; i++ )
				(*func)(farg,fill);
	}
}

static	_prt10(num,str)
	unsigned int num;
	char	*str;
{
	int	i;
	char	c, temp[6];

	temp[0]	= '\0';
	for(i = 1; i <= 5; i++)  {
		temp[i] = num % 10 + '0';
		num =/ 10;
	}
	for(i =	5; temp[i] == '0'; i--);
	if( i == 0 )
		i++;
	while( i >= 0 )
		*str++ = temp[i--];
}

static	_prtl10(num,str)
	long	num;
	char	*str;
{
	int	i;
	char	c, temp[11];

	temp[0]	= '\0';
	for(i = 1; i <= 10; i++)  {
		temp[i] = num % 10 + '0';
		num =/ 10;
	}
	for(i = 10; temp[i] == '0'; i--);
	if( i == 0 )
		i++;
	while( i >= 0 )
		*str++ = temp[i--];
}

static	_prt8(num,str)
	unsigned int num;
	char	*str;
{
	int	i;
	char	c;
	char	temp[7];

	temp[0]	= '\0';
	for(i = 1; i <= 6; i++)  {
		temp[i]	= (num & 07) + '0';
		num = (num >> 3) & 0037777;
	}
	temp[6] &= '1';
	for(i = 6; temp[i] == '0'; i--);
	if( i == 0 )
		i++;
	while( i >= 0 )
		*str++ = temp[i--];
}

static	_prtl8(num,str)
	long	num;
	char	*str;
{
	int	i;
	char	c, temp[12];

	temp[0]	= '\0';
	for(i = 1; i <= 11; i++)  {
		temp[i]	= (num & 07) + '0';
		num = num >> 3;
	}
	temp[11] &= '3';
	for(i = 11; temp[i] == '0'; i--);
	if( i == 0 )
		i++;
	while( i >= 0 )
		*str++ = temp[i--];
}

static	_prt16(num,str)
	unsigned int num;
	char	*str;
{
	int	i;
	char	c, temp[5];

	temp[0] = '\0';
	for(i = 1; i <= 4; i++)  {
		temp[i] = "0123456789abcdef"[num & 0x0f];
		num = num >> 4;
	}
	for(i = 4; temp[i] == '0'; i--);
	if( i == 0 )
		i++;
	while( i >= 0 )
		*str++ = temp[i--];
}

static	_prtl16(num,str)
	long	num;
	char	*str;
{
	int	i;
	char	c, temp[9];

	temp[0] = '\0';
	for(i = 1; i <= 8; i++)  {
		temp[i] = "0123456789abcdef"[num & 0x0f];
		num = num >> 4;
	}
	for(i = 8; temp[i] == '0'; i--);
	if( i == 0 )
		i++;
	while( i >= 0 )
		*str++ = temp[i--];
}