Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / obp / tools / promif / common / prom_printf.c
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* Hypervisor Software File: prom_printf.c
5*
6* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
7*
8* - Do no alter or remove copyright notices
9*
10* - Redistribution and use of this software in source and binary forms, with
11* or without modification, are permitted provided that the following
12* conditions are met:
13*
14* - Redistribution of source code must retain the above copyright notice,
15* this list of conditions and the following disclaimer.
16*
17* - Redistribution in binary form must reproduce the above copyright notice,
18* this list of conditions and the following disclaimer in the
19* documentation and/or other materials provided with the distribution.
20*
21* Neither the name of Sun Microsystems, Inc. or the names of contributors
22* may be used to endorse or promote products derived from this software
23* without specific prior written permission.
24*
25* This software is provided "AS IS," without a warranty of any kind.
26* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
27* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
28* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
29* MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
30* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
31* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
32* OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
33* FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
34* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
35* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
36* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
37*
38* You acknowledge that this software is not designed, licensed or
39* intended for use in the design, construction, operation or maintenance of
40* any nuclear facility.
41*
42* ========== Copyright Header End ============================================
43*/
44/*
45 * Copyright (c) 2000-2003 Sun Microsystems, Inc.
46 * All rights reserved.
47 * Use is subject to license terms.
48 */
49
50#pragma ident "@(#)prom_printf.c 1.1 00/08/07 SMI"
51
52#include <sys/promif.h>
53#include <sys/promimpl.h>
54#include <sys/varargs.h>
55
56static void _doprint(const char *, va_list, char **);
57static void _printn(uint64_t, int, int, int, char **);
58
59/*
60 * Emit character functions...
61 */
62
63static void
64_pput_flush(char *start, char *end)
65{
66 while (prom_write(prom_stdout_ihandle(), start, end - start) == -1)
67 ;
68}
69
70static void
71_sput(char c, char **p)
72{
73 **p = c;
74 *p += 1;
75}
76
77/*VARARGS1*/
78void
79prom_printf(const char *fmt, ...)
80{
81 va_list adx;
82
83 va_start(adx, fmt);
84 _doprint(fmt, adx, (char **)0);
85 va_end(adx);
86}
87
88void
89prom_vprintf(const char *fmt, va_list adx)
90{
91 _doprint(fmt, adx, (char **)0);
92}
93
94/*VARARGS2*/
95char *
96prom_sprintf(char *s, const char *fmt, ...)
97{
98 char *bp = s;
99 va_list adx;
100
101 va_start(adx, fmt);
102 _doprint(fmt, adx, &bp);
103 *bp++ = (char)0;
104 va_end(adx);
105 return (s);
106}
107
108char *
109prom_vsprintf(char *s, const char *fmt, va_list adx)
110{
111 char *bp = s;
112
113 _doprint(fmt, adx, &bp);
114 *bp++ = (char)0;
115 return (s);
116}
117
118static void
119_doprint(const char *fmt, va_list adx, char **bp)
120{
121 int32_t b, c, i, pad, width, ells;
122 char *s, *start;
123 char localbuf[100], *lbp;
124 int64_t l;
125 uint64_t ul;
126
127 if (bp == 0) {
128 bp = &lbp;
129 lbp = &localbuf[0];
130 }
131 start = *bp;
132loop:
133 width = 0;
134 while ((c = *fmt++) != '%') {
135 if (c == '\0')
136 goto out;
137 if (c == '\n') {
138 _sput('\r', bp);
139 _sput('\n', bp);
140 if (start == localbuf) {
141 _pput_flush(start, *bp);
142 lbp = &localbuf[0];
143 }
144 } else
145 _sput((char)c, bp);
146 if (start == localbuf && (*bp - start > 80)) {
147 _pput_flush(start, *bp);
148 lbp = &localbuf[0];
149 }
150 }
151
152 c = *fmt++;
153 for (pad = ' '; c == '0'; c = *fmt++)
154 pad = '0';
155
156 for (width = 0; c >= '0' && c <= '9'; c = *fmt++)
157 width = width * 10 + c - '0';
158
159 for (ells = 0; c == 'l'; c = *fmt++)
160 ells++;
161
162 switch (c) {
163 case 'i':
164 case 'd':
165 case 'D':
166 b = 10;
167 if (ells == 0)
168 l = (int64_t)va_arg(adx, int);
169 else if (ells == 1)
170 l = (int64_t)va_arg(adx, int64_t);
171 else
172 l = (int64_t)va_arg(adx, int64_t);
173 if (l < 0) {
174 _sput('-', bp);
175 width--;
176 ul = -l;
177 } else
178 ul = l;
179 goto number;
180
181 case 'p':
182 ells = 1;
183 /*FALLTHROUGH*/
184 case 'x':
185 case 'X':
186 b = 16;
187 goto u_number;
188
189 case 'u':
190 b = 10;
191 goto u_number;
192
193 case 'o':
194 case 'O':
195 b = 8;
196u_number:
197 if (ells == 0)
198 ul = (uint64_t)va_arg(adx, uint32_t);
199 else if (ells == 1)
200 ul = (uint64_t)va_arg(adx, uint64_t);
201 else
202 ul = (uint64_t)va_arg(adx, uint64_t);
203number:
204 _printn(ul, b, width, pad, bp);
205 break;
206
207 case 'c':
208 b = va_arg(adx, int);
209 for (i = 24; i >= 0; i -= 8)
210 if ((c = ((b >> i) & 0x7f)) != 0) {
211 if (c == '\n')
212 _sput('\r', bp);
213 _sput((char)c, bp);
214 }
215 break;
216
217 case 's':
218 s = va_arg(adx, char *);
219 while ((c = *s++) != 0) {
220 if (c == '\n')
221 _sput('\r', bp);
222 _sput((char)c, bp);
223 if (start == localbuf && (*bp - start > 80)) {
224 _pput_flush(start, *bp);
225 lbp = &localbuf[0];
226 }
227 }
228 break;
229
230 case '%':
231 _sput('%', bp);
232 break;
233 }
234 if (start == localbuf && (*bp - start > 80)) {
235 _pput_flush(start, *bp);
236 lbp = &localbuf[0];
237 }
238 goto loop;
239out:
240 if (start == localbuf && (*bp - start > 0))
241 _pput_flush(start, *bp);
242}
243
244/*
245 * Printn prints a number n in base b.
246 * We don't use recursion to avoid deep kernel stacks.
247 */
248static void
249_printn(uint64_t n, int32_t b, int32_t width, int32_t pad, char **bp)
250{
251 char prbuf[40];
252 char *cp;
253
254 cp = prbuf;
255 do {
256 *cp++ = "0123456789abcdef"[n%b];
257 n /= b;
258 width--;
259 } while (n);
260 while (width-- > 0)
261 *cp++ = (char)pad;
262 do {
263 _sput(*--cp, bp);
264 } while (cp > prbuf);
265}