Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / hypervisor / src / sample / lib / doprint.c
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* Hypervisor Software File: doprint.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 2003 Sun Microsystems, Inc. All rights reserved.
46 * Use is subject to license terms.
47 */
48
49#pragma ident "@(#)doprint.c 1.2 03/11/10 SMI"
50
51#include <limits.h>
52#include <sys/types.h>
53#include <stdarg.h>
54
55#define ADDCHAR(c) if (bufp++ - buf < buflen) \
56 bufp[-1] = (c); \
57 else if (print) (void)print((c))
58
59
60/*
61 * Given a buffer 'buf' of size 'buflen', render as much of the string
62 * described by <fmt, args> as possible. The string will always be
63 * null-terminated, so the maximum string length is 'buflen - 1'.
64 * Returns the number of bytes that would be necessary to render the
65 * entire string, not including null terminator (just like vsnprintf(3S)).
66 * To determine buffer size in advance, use _doprint(NULL, 0, fmt, args, 0) + 1.
67 */
68int
69_doprint(char *buf, size_t buflen, const char *fmt, va_list args, int (*print)(char c))
70{
71 uint64_t ul, tmp;
72 char *bufp = buf; /* current buffer pointer */
73 int pad, width, ells, base, sign, c;
74 char *digits, *sp, *bs;
75 char numbuf[65]; /* sufficient for a 64-bit binary value */
76
77 if ((ssize_t)buflen < 0)
78 buflen = 0;
79
80 while ((c = *fmt++) != '\0') {
81 if (c != '%') {
82 ADDCHAR(c);
83 continue;
84 }
85
86 if ((c = *fmt++) == '\0')
87 break;
88
89 for (pad = ' '; c == '0'; c = *fmt++)
90 pad = '0';
91
92 for (width = 0; c >= '0' && c <= '9'; c = *fmt++)
93 width = width * 10 + c - '0';
94
95 for (ells = 0; c == 'l'; c = *fmt++)
96 ells++;
97
98 digits = "0123456789abcdef";
99
100 if (c >= 'A' && c <= 'Z') {
101 c += 'a' - 'A';
102 digits = "0123456789ABCDEF";
103 }
104
105 base = sign = 0;
106
107 switch (c) {
108 case 'd':
109 sign = 1;
110 /*FALLTHROUGH*/
111 case 'u':
112 base = 10;
113 break;
114 case 'p':
115 ells = 1;
116 /*FALLTHROUGH*/
117 case 'x':
118 base = 16;
119 break;
120 case 'o':
121 base = 8;
122 break;
123 case 'b':
124 ells = 0;
125 base = 1;
126 break;
127 case 'c':
128 ul = (int64_t)va_arg(args, int);
129 ADDCHAR((int)ul & 0x7f);
130 break;
131 case 's':
132 sp = va_arg(args, char *);
133 if (sp == NULL)
134 sp = "<null string>";
135 while ((c = *sp++) != 0)
136 ADDCHAR(c);
137 break;
138 case '%':
139 ADDCHAR('%');
140 break;
141 }
142
143 if (base == 0)
144 continue;
145
146 if (ells == 0)
147 ul = (int64_t)va_arg(args, int);
148 else if (ells == 1)
149 ul = (int64_t)va_arg(args, long);
150 else
151 ul = (int64_t)va_arg(args, int64_t);
152
153 if (sign && (int64_t)ul < 0)
154 ul = -ul;
155 else
156 sign = 0;
157
158 if (ells < 8 / sizeof (long))
159 ul &= 0xffffffffU;
160
161 if (c == 'b') {
162 bs = va_arg(args, char *);
163 base = *bs++;
164 }
165
166 tmp = ul;
167 do {
168 width--;
169 } while ((tmp /= base) != 0);
170
171 if (sign && pad == '0')
172 ADDCHAR('-');
173 while (width-- > sign)
174 ADDCHAR(pad);
175 if (sign && pad == ' ')
176 ADDCHAR('-');
177
178 sp = numbuf;
179 tmp = ul;
180 do {
181 *sp++ = digits[tmp % base];
182 } while ((tmp /= base) != 0);
183
184 while (sp > numbuf) {
185 sp--;
186 ADDCHAR(*sp);
187 }
188
189 if (c == 'b' && ul != 0) {
190 int any = 0;
191 c = *bs++;
192 while (c != 0) {
193 if (ul & (1 << (c - 1))) {
194 if (any++ == 0)
195 ADDCHAR('<');
196 while ((c = *bs++) >= 32)
197 ADDCHAR(c);
198 ADDCHAR(',');
199 } else {
200 while ((c = *bs++) >= 32)
201 continue;
202 }
203 }
204 if (any) {
205 bufp--;
206 ADDCHAR('>');
207 }
208 }
209 }
210 if (bufp - buf < buflen)
211 bufp[0] = c;
212 else if (buflen != 0)
213 buf[buflen - 1] = c;
214 return (bufp - buf);
215}