summaryrefslogtreecommitdiff
path: root/system/alpha/console/printf.c
diff options
context:
space:
mode:
Diffstat (limited to 'system/alpha/console/printf.c')
-rw-r--r--system/alpha/console/printf.c301
1 files changed, 301 insertions, 0 deletions
diff --git a/system/alpha/console/printf.c b/system/alpha/console/printf.c
new file mode 100644
index 000000000..3d8cb4108
--- /dev/null
+++ b/system/alpha/console/printf.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * Copyright (c) 1993 The Hewlett-Packard Development Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include "m5op.h"
+
+/* The string s is terminated by a '\0' */
+void
+PutString(const 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(const 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(long value, int radix, int width, char fill)
+{
+ char buffer[40];
+ uint bufferindex = 0;
+ ulong uvalue;
+ ushort digit;
+ ushort left = 0;
+ ushort negative = 0;
+
+ if (fill == 0)
+ fill = ' ';
+
+ if (width < 0) {
+ width = -width;
+ left = 1;
+ }
+
+ if (width < 0 || width > 80)
+ width = 0;
+
+ if (radix < 0) {
+ radix = -radix;
+ if (value < 0) {
+ negative = 1;
+ value = -value;
+ }
+ }
+
+ switch (radix) {
+ case 8:
+ case 10:
+ case 16:
+ break;
+
+ default:
+ PutString("****");
+ return;
+ }
+
+ uvalue = value;
+
+ do {
+ if (radix != 16) {
+ digit = (ushort)(uvalue % radix);
+ uvalue /= radix;
+ } else {
+ digit = (ushort)(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 ((uint)width <= bufferindex) {
+ PutStringReverse(buffer, bufferindex);
+ } else {
+ width -= bufferindex;
+ if (!left)
+ PutRepChar(fill, width);
+ PutStringReverse(buffer, bufferindex);
+ if (left)
+ PutRepChar(fill, width);
+ }
+}
+
+ulong
+power(long base, long n)
+{
+ ulong p;
+
+ for (p = 1; n > 0; --n)
+ p = p * base;
+ return p;
+}
+
+void
+putFloat(double a, int fieldwidth, char fill)
+{
+ int i;
+ ulong b;
+
+ /*
+ * Put out everything before the decimal place.
+ */
+ PutNumber(((ulong) 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 = (ulong)(power(10, i) * (double)(a - (ulong) a));
+ PutChar((char)(b % 10) + '0');
+ }
+}
+
+const char *
+FormatItem(const char *f, va_list *ap)
+{
+ char c;
+ int fieldwidth = 0;
+ int leftjust = 0;
+ 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 = 1;
+ break;
+ case 'c': {
+ char a = (char)va_arg(*ap, int);
+
+ if (leftjust)
+ PutChar(a & 0x7f);
+ if (fieldwidth > 0)
+ PutRepChar(fill, fieldwidth - 1);
+ if (!leftjust)
+ PutChar(a & 0x7f);
+ return(f);
+ }
+ case 's': {
+ const char *a = va_arg(*ap, const char *);
+
+ 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);
+ 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;
+
+ long a = va_arg(*ap, long);
+ PutNumber(a, radix, fieldwidth, fill);
+
+ return(f);
+}
+
+int
+printf(const 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 */
+ return 0;
+}
+
+void
+panic(const 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 */
+ m5_panic();
+}