2005-06-05 00:59:06 +02:00
|
|
|
/*
|
|
|
|
Copyright 1993, 1994 Hewlett-Packard Development Company, L.P.
|
2003-11-14 16:52:42 +01:00
|
|
|
|
2005-06-05 00:59:06 +02:00
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
|
|
this software and associated documentation files (the "Software"), to deal in
|
|
|
|
the Software without restriction, including without limitation the rights to
|
|
|
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
|
|
of the Software, and to permit persons to whom the Software is furnished to do
|
|
|
|
so, subject to the following conditions:
|
2003-11-14 16:52:42 +01:00
|
|
|
|
2005-06-05 00:59:06 +02:00
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
|
|
copies or substantial portions of the Software.
|
2003-11-14 16:52:42 +01:00
|
|
|
|
2005-06-05 00:59:06 +02:00
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
|
SOFTWARE.
|
|
|
|
*/
|
2003-11-14 16:52:42 +01:00
|
|
|
|
|
|
|
#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
|
|
|
|
*/
|
|
|
|
|
2004-05-18 01:23:48 +02:00
|
|
|
//#include "system.h"
|
2003-11-14 16:52:42 +01:00
|
|
|
#include "lib.h"
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* The string s is terminated by a '\0' */
|
2003-11-14 18:32:52 +01:00
|
|
|
void
|
|
|
|
PutString(const char *s)
|
2003-11-14 16:52:42 +01:00
|
|
|
{
|
|
|
|
while (*s) PutChar(*s++);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* print c count times */
|
2003-11-14 18:32:52 +01:00
|
|
|
void
|
|
|
|
PutRepChar(char c, int count)
|
2003-11-14 16:52:42 +01:00
|
|
|
{
|
|
|
|
while (count--) PutChar(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* put string reverse */
|
2003-11-14 18:32:52 +01:00
|
|
|
void
|
|
|
|
PutStringReverse(const char *s, int index)
|
2003-11-14 16:52:42 +01:00
|
|
|
{
|
|
|
|
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 ' '
|
|
|
|
*/
|
2003-11-14 18:32:52 +01:00
|
|
|
void
|
|
|
|
PutNumber(sl value, int radix, int width, char fill)
|
2003-11-14 16:52:42 +01:00
|
|
|
{
|
|
|
|
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');
|
|
|
|
}
|
|
|
|
}
|
2003-11-14 18:32:52 +01:00
|
|
|
const char *
|
|
|
|
FormatItem(const char *f, va_list *ap)
|
2003-11-14 16:52:42 +01:00
|
|
|
{
|
|
|
|
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': {
|
2004-05-17 23:49:19 +02:00
|
|
|
char a = va_arg(*ap, char *);
|
2003-11-14 16:52:42 +01:00
|
|
|
|
|
|
|
if (leftjust) PutChar(a & 0x7f);
|
|
|
|
if (fieldwidth > 0) PutRepChar(fill, fieldwidth - 1);
|
|
|
|
if (!leftjust) PutChar(a & 0x7f);
|
|
|
|
return(f);
|
|
|
|
}
|
|
|
|
case 's': {
|
2003-11-14 18:32:52 +01:00
|
|
|
const char *a = va_arg(*ap, const char *);
|
2003-11-14 16:52:42 +01:00
|
|
|
|
2003-11-14 18:32:52 +01:00
|
|
|
if (leftjust) PutString((const char *) a);
|
|
|
|
if (fieldwidth > strlen((const char *) a))
|
|
|
|
PutRepChar(fill, fieldwidth - strlen((const char *)a));
|
|
|
|
if (!leftjust) PutString((const char *) a);
|
2003-11-14 16:52:42 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2003-11-14 18:32:52 +01:00
|
|
|
int
|
|
|
|
printf(const char *f, ...)
|
2003-11-14 16:52:42 +01:00
|
|
|
{
|
|
|
|
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 */
|
2003-11-14 18:32:52 +01:00
|
|
|
return 0;
|
2003-11-14 16:52:42 +01:00
|
|
|
}
|
|
|
|
|
2003-11-14 18:32:52 +01:00
|
|
|
void
|
|
|
|
panic(const char *f, ...)
|
2003-11-14 16:52:42 +01:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|