Xinu7/src/cmd/download/OLD/eload/lib/printf.c
/* 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--];
}