summaryrefslogtreecommitdiff
path: root/usr/src/psm/promif/ieee1275/common/prom_printf.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/psm/promif/ieee1275/common/prom_printf.c')
-rw-r--r--usr/src/psm/promif/ieee1275/common/prom_printf.c242
1 files changed, 242 insertions, 0 deletions
diff --git a/usr/src/psm/promif/ieee1275/common/prom_printf.c b/usr/src/psm/promif/ieee1275/common/prom_printf.c
new file mode 100644
index 0000000000..e510540310
--- /dev/null
+++ b/usr/src/psm/promif/ieee1275/common/prom_printf.c
@@ -0,0 +1,242 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1995-1996, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/promif.h>
+#include <sys/promimpl.h>
+#include <sys/varargs.h>
+
+static void _doprint(const char *, va_list, char **);
+static void _printn(uint64_t, int, int, int, char **);
+
+/*
+ * Emit character functions...
+ */
+
+static void
+_pput_flush(char *start, char *end)
+{
+ while (prom_write(prom_stdout_ihandle(),
+ start, end - start, 0, BYTE) == -1)
+ ;
+}
+
+static void
+_sput(char c, char **p)
+{
+ **p = c;
+ *p += 1;
+}
+
+/*VARARGS1*/
+void
+prom_printf(const char *fmt, ...)
+{
+ va_list adx;
+
+ va_start(adx, fmt);
+ _doprint(fmt, adx, (char **)0);
+ va_end(adx);
+}
+
+void
+prom_vprintf(const char *fmt, va_list adx)
+{
+ _doprint(fmt, adx, (char **)0);
+}
+
+/*VARARGS2*/
+char *
+prom_sprintf(char *s, const char *fmt, ...)
+{
+ char *bp = s;
+ va_list adx;
+
+ va_start(adx, fmt);
+ _doprint(fmt, adx, &bp);
+ *bp++ = (char)0;
+ va_end(adx);
+ return (s);
+}
+
+char *
+prom_vsprintf(char *s, const char *fmt, va_list adx)
+{
+ char *bp = s;
+
+ _doprint(fmt, adx, &bp);
+ *bp++ = (char)0;
+ return (s);
+}
+
+static void
+_doprint(const char *fmt, va_list adx, char **bp)
+{
+ int b, c, i, pad, width, ells;
+ char *s, *start;
+ char localbuf[100], *lbp;
+ int64_t l;
+ uint64_t ul;
+
+ if (bp == 0) {
+ bp = &lbp;
+ lbp = &localbuf[0];
+ }
+ start = *bp;
+loop:
+ width = 0;
+ while ((c = *fmt++) != '%') {
+ if (c == '\0')
+ goto out;
+ if (c == '\n') {
+ _sput('\r', bp);
+ _sput('\n', bp);
+ if (start == localbuf) {
+ _pput_flush(start, *bp);
+ lbp = &localbuf[0];
+ }
+ } else
+ _sput((char)c, bp);
+ if (start == localbuf && (*bp - start > 80)) {
+ _pput_flush(start, *bp);
+ lbp = &localbuf[0];
+ }
+ }
+
+ c = *fmt++;
+ for (pad = ' '; c == '0'; c = *fmt++)
+ pad = '0';
+
+ for (width = 0; c >= '0' && c <= '9'; c = *fmt++)
+ width = width * 10 + c - '0';
+
+ for (ells = 0; c == 'l'; c = *fmt++)
+ ells++;
+
+ switch (c) {
+ case 'd':
+ case 'D':
+ b = 10;
+ if (ells == 0)
+ l = (int64_t)va_arg(adx, int);
+ else if (ells == 1)
+ l = (int64_t)va_arg(adx, long);
+ else
+ l = (int64_t)va_arg(adx, int64_t);
+ if (l < 0) {
+ _sput('-', bp);
+ width--;
+ ul = -l;
+ } else
+ ul = l;
+ goto number;
+
+ case 'p':
+ ells = 1;
+ /*FALLTHROUGH*/
+ case 'x':
+ case 'X':
+ b = 16;
+ goto u_number;
+
+ case 'u':
+ b = 10;
+ goto u_number;
+
+ case 'o':
+ case 'O':
+ b = 8;
+u_number:
+ if (ells == 0)
+ ul = (uint64_t)va_arg(adx, u_int);
+ else if (ells == 1)
+ ul = (uint64_t)va_arg(adx, u_long);
+ else
+ ul = (uint64_t)va_arg(adx, uint64_t);
+number:
+ _printn(ul, b, width, pad, bp);
+ break;
+
+ case 'c':
+ b = va_arg(adx, int);
+ for (i = 24; i >= 0; i -= 8)
+ if ((c = ((b >> i) & 0x7f)) != 0) {
+ if (c == '\n')
+ _sput('\r', bp);
+ _sput((char)c, bp);
+ }
+ break;
+
+ case 's':
+ s = va_arg(adx, char *);
+ while ((c = *s++) != 0) {
+ if (c == '\n')
+ _sput('\r', bp);
+ _sput((char)c, bp);
+ if (start == localbuf && (*bp - start > 80)) {
+ _pput_flush(start, *bp);
+ lbp = &localbuf[0];
+ }
+ }
+ break;
+
+ case '%':
+ _sput('%', bp);
+ break;
+ }
+ if (start == localbuf && (*bp - start > 80)) {
+ _pput_flush(start, *bp);
+ lbp = &localbuf[0];
+ }
+ goto loop;
+out:
+ if (start == localbuf && (*bp - start > 0))
+ _pput_flush(start, *bp);
+}
+
+/*
+ * Printn prints a number n in base b.
+ * We don't use recursion to avoid deep kernel stacks.
+ */
+static void
+_printn(uint64_t n, int b, int width, int pad, char **bp)
+{
+ char prbuf[40];
+ char *cp;
+
+ cp = prbuf;
+ do {
+ *cp++ = "0123456789abcdef"[n%b];
+ n /= b;
+ width--;
+ } while (n);
+ while (width-- > 0)
+ *cp++ = (char)pad;
+ do {
+ _sput(*--cp, bp);
+ } while (cp > prbuf);
+}