gem5/system/alpha/console/printf.c
2003-11-14 10:52:42 -05:00

299 lines
6.7 KiB
C

/*****************************************************************************
Copyright © 1993, 1994 Digital Equipment Corporation,
Maynard, Massachusetts.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted, provided
that the copyright notice and this permission notice appear in all copies
of software and supporting documentation, and that the name of Digital not
be used in advertising or publicity pertaining to distribution of the software
without specific, written prior permission. Digital grants this permission
provided that you prominently mark, as not part of the original, any
modifications made to this software or documentation.
Digital Equipment Corporation disclaims all warranties and/or guarantees
with regard to this software, including all implied warranties of fitness for
a particular purpose and merchantability, and makes no representations
regarding the use of, or the results of the use of, the software and
documentation in terms of correctness, accuracy, reliability, currentness or
otherwise; and you rely on the software, documentation and results solely at
your own risk.
******************************************************************************/
#ifndef LINT
static char *rcsid = "$Id: printf.c,v 1.1.1.1 1997/10/30 23:27:12 verghese Exp $";
#endif
/*
* $Log: printf.c,v $
* Revision 1.1.1.1 1997/10/30 23:27:12 verghese
* current 10/29/97
*
* Revision 1.1 1995/06/26 21:09:35 berc
* Initial revision
*
* Revision 1.8 1994/10/06 20:29:08 fdh
* Corrected unsigned long declaration.
*
* Revision 1.7 1994/08/05 20:16:23 fdh
* Updated Copyright header and RCS $Id: identifier.
*
* Revision 1.6 1994/06/21 15:41:54 rusling
* fixedup WNT compiler warnings
*
* Revision 1.5 1994/06/17 19:35:37 fdh
* Clean-up...
*
* Revision 1.4 1994/01/19 10:40:08 rusling
* Ported to Alpha Windows NT.
*
* Revision 1.3 1993/11/02 21:57:45 fdh
* Fixed sign extension problem introduced in version 1.2
*
* Revision 1.2 1993/10/13 15:29:02 rusling
* Added floating point support in printf. This meant adding variable arguments to
* it and FormatItem() and including stdarg.h.
*
* Revision 1.1 1993/06/08 19:56:24 fdh
* Initial revision
*
*/
/* printf.c
L. S.
Sun Feb 10 20:18:22 1985
*/
#include "system.h"
#include "lib.h"
#include <stdarg.h>
/* The string s is terminated by a '\0' */
void PutString(char *s)
{
while (*s) PutChar(*s++);
}
/* print c count times */
void PutRepChar(char c, int count)
{
while (count--) PutChar(c);
}
/* put string reverse */
void PutStringReverse(char *s, int index)
{
while ((index--) > 0) PutChar(s[index]);
}
/* prints value in radix, in a field width width, with fill
character fill
if radix is negative, print as signed quantity
if width is negative, left justify
if width is 0, use whatever is needed
if fill is 0, use ' '
*/
void PutNumber(sl value, int radix, int width, char fill)
{
char buffer[40];
ui bufferindex = 0;
ul uvalue;
uw digit;
uw left = FALSE;
uw negative = FALSE;
if (fill == 0) fill = ' ';
if (width < 0) {
width = -width;
left = TRUE;
}
if (width < 0 || width > 80) width = 0;
if (radix < 0) {
radix = -radix;
if (value < 0) {
negative = TRUE;
value = -value;
}
}
switch (radix) {
case 8:
case 10:
case 16: break;
default: {
PutString("****");
return;
}
}
uvalue = value;
do {
if (radix != 16)
{
digit = (uw)(uvalue % radix);
uvalue /= radix;
}
else
{
digit = (uw)(uvalue & 0xf);
uvalue = uvalue >> 4;
}
buffer[bufferindex] = digit + ((digit <= 9) ? '0' : ('A' - 10));
bufferindex += 1;
} while (uvalue != 0);
/* fill # ' ' and negative cannot happen at once */
if (negative) {
buffer[bufferindex] = '-';
bufferindex += 1;
}
if ((ui)width <= bufferindex) PutStringReverse(buffer, bufferindex);
else {
width -= bufferindex;
if (!left) PutRepChar(fill, width);
PutStringReverse(buffer, bufferindex);
if (left) PutRepChar(fill, width);
}
}
ul power(long base, long n)
{
ul p;
for (p = 1; n > 0; --n)
p = p * base;
return p;
}
void putFloat(double a, int fieldwidth, char fill)
{
int i;
ul b;
/*
* Put out everything before the decimal place.
*/
PutNumber(((ul) a), 10, fieldwidth, fill);
/*
* Output the decimal place.
*/
PutChar('.' & 0x7f);
/*
* Output the n digits after the decimal place.
*/
for (i = 1; i < 6; i++) {
b = (ul)(power(10, i) * (double)(a - (ul) a));
PutChar((char)(b % 10) + '0');
}
}
char *FormatItem(char *f, va_list *ap)
{
char c;
int fieldwidth = 0;
int leftjust = FALSE;
int radix = 0;
char fill = ' ';
if (*f == '0') fill = '0';
while (c = *f++) {
if (c >= '0' && c <= '9') {
fieldwidth = (fieldwidth * 10) + (c - '0');
}
else switch (c) {
case '\000': return(--f);
case '%': PutChar('%');
return(f);
case '-': leftjust = TRUE;
break;
case 'c': {
char a = va_arg(*ap, char);
if (leftjust) PutChar(a & 0x7f);
if (fieldwidth > 0) PutRepChar(fill, fieldwidth - 1);
if (!leftjust) PutChar(a & 0x7f);
return(f);
}
case 's': {
char *a = va_arg(*ap, char *);
if (leftjust) PutString((char *) a);
if (fieldwidth > strlen((char *) a))
PutRepChar(fill, fieldwidth - strlen((char *)a));
if (!leftjust) PutString((char *) a);
return(f);
}
case 'd': radix = -10;
break;
case 'u': radix = 10;
break;
case 'x': radix = 16;
break;
case 'X': radix = 16;
break;
case 'o': radix = 8;
break;
case 'f': {
double a = va_arg(*ap, double);
putFloat(a, fieldwidth, fill);
return(f);
}
default: /* unknown switch! */
radix = 3;
break;
}
if (radix) break;
}
if (leftjust) fieldwidth = -fieldwidth;
{
sl a = va_arg(*ap, sl);
PutNumber(a, radix, fieldwidth, fill);
}
return(f);
}
void printf(char *f, ...)
{
va_list ap;
va_start(ap, f);
while (*f) {
if (*f == '%') f = FormatItem(f + 1, &ap);
else PutChar(*f++);
}
if (*(f-1)=='\n') {
/* add a line-feed (SimOS console output goes to shell */
PutChar('\r');
}
va_end(ap); /* clean up */
}
void panic(char *f, ...)
{
va_list ap;
va_start(ap, f);
printf("CONSOLE PANIC (looping): ");
while (*f) {
if (*f == '%') f = FormatItem(f + 1, &ap);
else PutChar(*f++);
}
va_end(ap); /* clean up */
while(1);
}