Chameleon

Chameleon Svn Source Tree

Root/trunk/i386/libsa/prf.c

1/*
2 * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 2.0 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24/*
25 * Mach Operating System
26 * Copyright (c) 1990 Carnegie-Mellon University
27 * Copyright (c) 1989 Carnegie-Mellon University
28 * Copyright (c) 1988 Carnegie-Mellon University
29 * Copyright (c) 1987 Carnegie-Mellon University
30 * All rights reserved. The CMU software License Agreement specifies
31 * the terms and conditions for use and redistribution.
32 */
33/*
34 * Copyright (c) 1982, 1986 Regents of the University of California.
35 * All rights reserved. The Berkeley software License Agreement
36 * specifies the terms and conditions for redistribution.
37 *
38 *@(#)prf.c7.1 (Berkeley) 6/5/86
39 */
40
41#include <stdarg.h>
42
43#define SPACE1
44#define ZERO2
45#define UCASE16
46#define SIGNED32
47
48/*
49 * Scaled down version of C Library printf.
50 * Used to print diagnostic information directly on console tty.
51 * Since it is not interrupt driven, all system activities are
52 * suspended.
53 *
54 */
55
56#define DIVIDEND_LOW *(unsigned int*) dividend
57#define DIVIDEND_HIGH ((unsigned int*) dividend)[1]
58
59/*
60 * Divides 64-bit dividend by 32-bit divisor.
61 * Quotient stored in dividend, remainder returned.
62 * Assumes little-endian byte order.
63 * Assumes divisor is non-zero.
64 */
65unsigned int i386_unsigned_div(
66unsigned long long* dividend,
67unsigned int divisor
68)
69{
70unsigned int high = DIVIDEND_HIGH;
71
72if (high >= divisor)
73{
74__asm__ volatile ("xorl %%edx, %%edx; divl %2" : "=a"(DIVIDEND_HIGH), "=d"(high) : "r"(divisor), "a"(high));
75}
76else
77{
78DIVIDEND_HIGH = 0;
79}
80__asm__ volatile("divl %2" : "+a"(DIVIDEND_LOW), "+d"(high) : "r"(divisor));
81return high;
82}
83
84#undef DIVIDEND_HIGH
85#undef DIVIDEND_LOW
86
87/*
88 * Printn prints a number n in base b.
89 * We don't use recursion to avoid deep kernel stacks.
90 */
91static int printn(
92unsigned long long n,
93int b,
94int flag,
95int minwidth,
96int (*putfn_p)(),
97void* putfn_arg
98)
99{
100char prbuf[22];
101register char *cp;
102int width = 0, neg = 0;
103static const char hexdig[] = "0123456789abcdef0123456789ABCDEF";
104
105if ((flag & SIGNED) && (long long)n < 0)
106{
107neg = 1;
108n = (unsigned long long)(-(long long)n);
109}
110cp = prbuf;
111if ((b & -b) == b)// b is a power of 2
112{
113unsigned int log2b = (unsigned int) (__builtin_ctz((unsigned int) b) & 31);
114unsigned int mask = (unsigned int) (b - 1);
115do
116{
117*cp++ = hexdig[(flag & UCASE) + (int) (n & mask)];
118n >>= log2b;
119width++;
120}
121while (n);
122}
123else// b is not a power of 2
124{
125do
126{
127*cp++ = hexdig[(flag & UCASE) + (int) i386_unsigned_div(&n, (unsigned int) b)];
128width++;
129}
130while (n);
131}
132
133if (neg)
134{
135if (putfn_p)
136{
137(void)(*putfn_p)('-', putfn_arg);
138}
139width++;
140}
141if (!putfn_p)
142{
143return (width < minwidth) ? minwidth : width;
144}
145for (;width < minwidth; width++)
146(void)(*putfn_p)( (flag & ZERO) ? '0' : ' ', putfn_arg);
147
148do
149(void)(*putfn_p)(*--cp, putfn_arg);
150while (cp > prbuf);
151return width;
152}
153
154/*
155 * Printp prints a pointer.
156 */
157static int printp(
158const void* p,
159int minwidth,
160int (*putfn_p)(),
161void* putfn_arg
162)
163{
164int width = 0;
165
166if (p)
167{
168if (putfn_p)
169{
170(void)(*putfn_p)('0', putfn_arg);
171(void)(*putfn_p)('x', putfn_arg);
172}
173width = 2;
174minwidth = ((minwidth >= 2) ? (minwidth - 2) : 0);
175}
176return width + printn((unsigned long long) p, 16, ZERO, minwidth, putfn_p, putfn_arg);
177}
178
179int prf(
180const char *fmt,
181va_list ap,
182int (*putfn_p)(),
183void *putfn_arg
184)
185{
186int b, c, len = 0;
187const char *s;
188int flag, width, ells;
189int minwidth;
190
191loop:
192while ((c = *fmt++) != '%')
193{
194if(c == '\0')
195{
196return len;
197}
198
199if (putfn_p)
200{
201(void)(*putfn_p)(c, putfn_arg);
202}
203len++;
204}
205minwidth = 0;
206flag = 0;
207ells = 0;
208again:
209c = *fmt++;
210switch (c)
211{
212case 'l':
213if (ells < 2)
214{
215++ells;
216}
217goto again;
218case ' ':
219flag |= SPACE;
220goto again;
221case '0':
222if (minwidth == 0)
223{
224/* this is a flag */
225flag |= ZERO;
226goto again;
227} /* fall through */
228case '1':
229case '2':
230case '3':
231case '4':
232case '5':
233case '6':
234case '7':
235case '8':
236case '9':
237minwidth *= 10;
238minwidth += c - '0';
239goto again;
240case 'X':
241flag |= UCASE;
242/* fall through */
243case 'x':
244b = 16;
245goto number;
246case 'd':
247case 'i':
248flag |= SIGNED;
249/* fall through */
250case 'u':
251b = 10;
252goto number;
253case 'o': case 'O':
254b = 8;
255number:
256switch (ells)
257{
258case 2:
259len += printn(va_arg(ap, unsigned long long), b, flag, minwidth, putfn_p, putfn_arg);
260break;
261case 1:
262len += printn(va_arg(ap, unsigned long), b, flag, minwidth, putfn_p, putfn_arg);
263break;
264default:
265len += printn(va_arg(ap, unsigned int), b, flag, minwidth, putfn_p, putfn_arg);
266break;
267}
268break;
269case 's':
270s = va_arg(ap, const char*);
271if (!s)
272{
273s = "(null)";
274}
275width = 0;
276if (!putfn_p)
277{
278while ((c = *s++))
279{
280width++;
281}
282len += ((width < minwidth) ? minwidth : width);
283break;
284}
285while ((c = *s++))
286{
287(void)(*putfn_p)(c, putfn_arg);
288len++;
289width++;
290}
291while (width++ < minwidth)
292{
293(void)(*putfn_p)(' ', putfn_arg);
294len++;
295}
296break;
297case 'c':
298if (putfn_p)
299{
300(void)(*putfn_p)((char) va_arg(ap, int), putfn_arg);
301}
302len++;
303break;
304case '%':
305if (putfn_p)
306{
307(void)(*putfn_p)('%', putfn_arg);
308}
309len++;
310break;
311case 'p':
312len += printp(va_arg(ap, const void*), minwidth, putfn_p, putfn_arg);
313break;
314case 'n':
315s = va_arg(ap, const char*);
316if (s)
317{
318*(int*) s = len;
319}
320break;
321default:
322break;
323}
324goto loop;
325}
326

Archive Download this file

Revision: 2887