|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * @OSF_COPYRIGHT@
24: */
25:
26: /*
27: * Mach Operating System
28: * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
29: * All Rights Reserved.
30: *
31: * Permission to use, copy, modify and distribute this software and its
32: * documentation is hereby granted, provided that both the copyright
33: * notice and this permission notice appear in all copies of the
34: * software, derivative works or modified versions, and any portions
35: * thereof, and that both notices appear in supporting documentation.
36: *
37: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
38: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
39: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
40: *
41: * Carnegie Mellon requests users of this software to return to
42: *
43: * Software Distribution Coordinator or [email protected]
44: * School of Computer Science
45: * Carnegie Mellon University
46: * Pittsburgh PA 15213-3890
47: *
48: * any improvements or extensions that they make and grant Carnegie Mellon
49: * the rights to redistribute these changes.
50: */
51:
52: /*
53: * Common code for printf et al.
54: *
55: * The calling routine typically takes a variable number of arguments,
56: * and passes the address of the first one. This implementation
57: * assumes a straightforward, stack implementation, aligned to the
58: * machine's wordsize. Increasing addresses are assumed to point to
59: * successive arguments (left-to-right), as is the case for a machine
60: * with a downward-growing stack with arguments pushed right-to-left.
61: *
62: * To write, for example, fprintf() using this routine, the code
63: *
64: * fprintf(fd, format, args)
65: * FILE *fd;
66: * char *format;
67: * {
68: * _doprnt(format, &args, fd);
69: * }
70: *
71: * would suffice. (This example does not handle the fprintf's "return
72: * value" correctly, but who looks at the return value of fprintf
73: * anyway?)
74: *
75: * This version implements the following printf features:
76: *
77: * %d decimal conversion
78: * %u unsigned conversion
79: * %x hexadecimal conversion
80: * %X hexadecimal conversion with capital letters
81: * %o octal conversion
82: * %c character
83: * %s string
84: * %m.n field width, precision
85: * %-m.n left adjustment
86: * %0m.n zero-padding
87: * %*.* width and precision taken from arguments
88: *
89: * This version does not implement %f, %e, or %g. It accepts, but
90: * ignores, an `l' as in %ld, %lo, %lx, and %lu, and therefore will not
91: * work correctly on machines for which sizeof(long) != sizeof(int).
92: * It does not even parse %D, %O, or %U; you should be using %ld, %o and
93: * %lu if you mean long conversion.
94: *
95: * As mentioned, this version does not return any reasonable value.
96: *
97: * Permission is granted to use, modify, or propagate this code as
98: * long as this notice is incorporated.
99: *
100: * Steve Summit 3/25/87
101: */
102:
103: /*
104: * Added formats for decoding device registers:
105: *
106: * printf("reg = %b", regval, "<base><arg>*")
107: *
108: * where <base> is the output base expressed as a control character:
109: * i.e. '\10' gives octal, '\20' gives hex. Each <arg> is a sequence of
110: * characters, the first of which gives the bit number to be inspected
111: * (origin 1), and the rest (up to a control character (<= 32)) give the
112: * name of the register. Thus
113: * printf("reg = %b\n", 3, "\10\2BITTWO\1BITONE")
114: * would produce
115: * reg = 3<BITTWO,BITONE>
116: *
117: * If the second character in <arg> is also a control character, it
118: * indicates the last bit of a bit field. In this case, printf will extract
119: * bits <1> to <2> and print it. Characters following the second control
120: * character are printed before the bit field.
121: * printf("reg = %b\n", 0xb, "\10\4\3FIELD1=\2BITTWO\1BITONE")
122: * would produce
123: * reg = b<FIELD1=2,BITONE>
124: *
125: * The %B format is like %b but the bits are numbered from the most
126: * significant (the bit weighted 31), which is called 1, to the least
127: * significant, called 32.
128: */
129: /*
130: * Added for general use:
131: * # prefix for alternate format:
132: * 0x (0X) for hex
133: * leading 0 for octal
134: * + print '+' if positive
135: * blank print ' ' if positive
136: *
137: * z signed hexadecimal
138: * r signed, 'radix'
139: * n unsigned, 'radix'
140: *
141: * D,U,O,Z same as corresponding lower-case versions
142: * (compatibility)
143: */
144:
145: #include <platforms.h>
146: #include <mach/boolean.h>
147: #include <cpus.h>
148: #include <kern/cpu_number.h>
149: #include <kern/lock.h>
150: #include <kern/thread.h>
151: #include <kern/sched_prim.h>
152: #include <kern/misc_protos.h>
153: #include <stdarg.h>
154: #include <string.h>
155: #include <mach_assert.h>
156: #ifdef MACH_BSD
157: #include <sys/msgbuf.h>
158: #endif
159:
160: #ifdef __ppc__
161: #include <ppc/Firmware.h>
162: #endif
163:
164: /*
165: * Forward declarations
166: */
167: void printnum(
168: register unsigned int u,
169: register int base,
170: void (*putc)(char));
171:
172:
173: #define isdigit(d) ((d) >= '0' && (d) <= '9')
174: #define Ctod(c) ((c) - '0')
175:
176: #define MAXBUF (sizeof(long int) * 8) /* enough for binary */
177:
178: void
179: printnum(
180: register unsigned int u, /* number to print */
181: register int base,
182: void (*putc)(char))
183: {
184: char buf[MAXBUF]; /* build number here */
185: register char * p = &buf[MAXBUF-1];
186: static char digs[] = "0123456789abcdef";
187:
188: do {
189: *p-- = digs[u % base];
190: u /= base;
191: } while (u != 0);
192:
193: while (++p != &buf[MAXBUF])
194: (*putc)(*p);
195:
196: }
197:
198: boolean_t _doprnt_truncates = FALSE;
199:
200: void
201: _doprnt(
202: register const char *fmt,
203: va_list *argp,
204: /* character output routine */
205: void (*putc)(char),
206: int radix) /* default radix - for '%r' */
207: {
208: int length;
209: int prec;
210: boolean_t ladjust;
211: char padc;
212: long n;
213: unsigned long u;
214: int plus_sign;
215: int sign_char;
216: boolean_t altfmt, truncate;
217: int base;
218: register char c;
219: int capitals;
220:
221: while ((c = *fmt) != '\0') {
222: if (c != '%') {
223: (*putc)(c);
224: fmt++;
225: continue;
226: }
227:
228: fmt++;
229:
230: length = 0;
231: prec = -1;
232: ladjust = FALSE;
233: padc = ' ';
234: plus_sign = 0;
235: sign_char = 0;
236: altfmt = FALSE;
237:
238: while (TRUE) {
239: c = *fmt;
240: if (c == '#') {
241: altfmt = TRUE;
242: }
243: else if (c == '-') {
244: ladjust = TRUE;
245: }
246: else if (c == '+') {
247: plus_sign = '+';
248: }
249: else if (c == ' ') {
250: if (plus_sign == 0)
251: plus_sign = ' ';
252: }
253: else
254: break;
255: fmt++;
256: }
257:
258: if (c == '0') {
259: padc = '0';
260: c = *++fmt;
261: }
262:
263: if (isdigit(c)) {
264: while(isdigit(c)) {
265: length = 10 * length + Ctod(c);
266: c = *++fmt;
267: }
268: }
269: else if (c == '*') {
270: length = va_arg(*argp, int);
271: c = *++fmt;
272: if (length < 0) {
273: ladjust = !ladjust;
274: length = -length;
275: }
276: }
277:
278: if (c == '.') {
279: c = *++fmt;
280: if (isdigit(c)) {
281: prec = 0;
282: while(isdigit(c)) {
283: prec = 10 * prec + Ctod(c);
284: c = *++fmt;
285: }
286: }
287: else if (c == '*') {
288: prec = va_arg(*argp, int);
289: c = *++fmt;
290: }
291: }
292:
293: if (c == 'l')
294: c = *++fmt; /* need it if sizeof(int) < sizeof(long) */
295:
296: truncate = FALSE;
297: capitals=0; /* Assume lower case printing */
298:
299: switch(c) {
300: case 'b':
301: case 'B':
302: {
303: register char *p;
304: boolean_t any;
305: register int i;
306:
307: u = va_arg(*argp, unsigned long);
308: p = va_arg(*argp, char *);
309: base = *p++;
310: printnum(u, base, putc);
311:
312: if (u == 0)
313: break;
314:
315: any = FALSE;
316: while ((i = *p++) != '\0') {
317: if (*fmt == 'B')
318: i = 33 - i;
319: if (*p <= 32) {
320: /*
321: * Bit field
322: */
323: register int j;
324: if (any)
325: (*putc)(',');
326: else {
327: (*putc)('<');
328: any = TRUE;
329: }
330: j = *p++;
331: if (*fmt == 'B')
332: j = 32 - j;
333: for (; (c = *p) > 32; p++)
334: (*putc)(c);
335: printnum((unsigned)( (u>>(j-1)) & ((2<<(i-j))-1)),
336: base, putc);
337: }
338: else if (u & (1<<(i-1))) {
339: if (any)
340: (*putc)(',');
341: else {
342: (*putc)('<');
343: any = TRUE;
344: }
345: for (; (c = *p) > 32; p++)
346: (*putc)(c);
347: }
348: else {
349: for (; *p > 32; p++)
350: continue;
351: }
352: }
353: if (any)
354: (*putc)('>');
355: break;
356: }
357:
358: case 'c':
359: c = va_arg(*argp, int);
360: (*putc)(c);
361: break;
362:
363: case 's':
364: {
365: register char *p;
366: register char *p2;
367:
368: if (prec == -1)
369: prec = 0x7fffffff; /* MAXINT */
370:
371: p = va_arg(*argp, char *);
372:
373: if (p == (char *)0)
374: p = "";
375:
376: if (length > 0 && !ladjust) {
377: n = 0;
378: p2 = p;
379:
380: for (; *p != '\0' && n < prec; p++)
381: n++;
382:
383: p = p2;
384:
385: while (n < length) {
386: (*putc)(' ');
387: n++;
388: }
389: }
390:
391: n = 0;
392:
393: while (*p != '\0') {
394: if (++n > prec || (length > 0 && n > length))
395: break;
396:
397: (*putc)(*p++);
398: }
399:
400: if (n < length && ladjust) {
401: while (n < length) {
402: (*putc)(' ');
403: n++;
404: }
405: }
406:
407: break;
408: }
409:
410: case 'o':
411: truncate = _doprnt_truncates;
412: case 'O':
413: base = 8;
414: goto print_unsigned;
415:
416: case 'd':
417: truncate = _doprnt_truncates;
418: case 'D':
419: base = 10;
420: goto print_signed;
421:
422: case 'u':
423: truncate = _doprnt_truncates;
424: case 'U':
425: base = 10;
426: goto print_unsigned;
427:
428: case 'x':
429: truncate = _doprnt_truncates;
430: base = 16;
431: goto print_unsigned;
432:
433: case 'X':
434: base = 16;
435: capitals=16; /* Print in upper case */
436: goto print_unsigned;
437:
438: case 'z':
439: truncate = _doprnt_truncates;
440: base = 16;
441: goto print_signed;
442:
443: case 'Z':
444: base = 16;
445: capitals=16; /* Print in upper case */
446: goto print_signed;
447:
448: case 'r':
449: truncate = _doprnt_truncates;
450: case 'R':
451: base = radix;
452: goto print_signed;
453:
454: case 'n':
455: truncate = _doprnt_truncates;
456: case 'N':
457: base = radix;
458: goto print_unsigned;
459:
460: print_signed:
461: n = va_arg(*argp, long);
462: if (n >= 0) {
463: u = n;
464: sign_char = plus_sign;
465: }
466: else {
467: u = -n;
468: sign_char = '-';
469: }
470: goto print_num;
471:
472: print_unsigned:
473: u = va_arg(*argp, unsigned long);
474: goto print_num;
475:
476: print_num:
477: {
478: char buf[MAXBUF]; /* build number here */
479: register char * p = &buf[MAXBUF-1];
480: static char digits[] = "0123456789abcdef0123456789ABCDEF";
481: char *prefix = 0;
482:
483: if (truncate) u = (long)((int)(u));
484:
485: if (u != 0 && altfmt) {
486: if (base == 8)
487: prefix = "0";
488: else if (base == 16)
489: prefix = "0x";
490: }
491:
492: do {
493: /* Print in the correct case */
494: *p-- = digits[(u % base)+capitals];
495: u /= base;
496: } while (u != 0);
497:
498: length -= (&buf[MAXBUF-1] - p);
499: if (sign_char)
500: length--;
501: if (prefix)
502: length -= strlen((const char *) prefix);
503:
504: if (padc == ' ' && !ladjust) {
505: /* blank padding goes before prefix */
506: while (--length >= 0)
507: (*putc)(' ');
508: }
509: if (sign_char)
510: (*putc)(sign_char);
511: if (prefix)
512: while (*prefix)
513: (*putc)(*prefix++);
514: if (padc == '0') {
515: /* zero padding goes after sign and prefix */
516: while (--length >= 0)
517: (*putc)('0');
518: }
519: while (++p != &buf[MAXBUF])
520: (*putc)(*p);
521:
522: if (ladjust) {
523: while (--length >= 0)
524: (*putc)(' ');
525: }
526: break;
527: }
528:
529: case '\0':
530: fmt--;
531: break;
532:
533: default:
534: (*putc)(c);
535: }
536: fmt++;
537: }
538: }
539:
540: #if MP_PRINTF
541: boolean_t new_printf_cpu_number = FALSE;
542: #endif /* MP_PRINTF */
543:
544:
545: decl_simple_lock_data(,printf_lock)
546:
547: void
548: printf_init(void)
549: {
550: /*
551: * Lock is only really needed after the first thread is created.
552: */
553: simple_lock_init(&printf_lock, ETAP_MISC_PRINTF);
554: }
555:
556: /* derived from boot_gets */
557: void
558: safe_gets(
559: char *str,
560: int maxlen)
561: {
562: register char *lp;
563: register int c;
564: char *strmax = str + maxlen - 1; /* allow space for trailing 0 */
565:
566: lp = str;
567: for (;;) {
568: c = cngetc();
569: switch (c) {
570: case '\n':
571: case '\r':
572: printf("\n");
573: *lp++ = 0;
574: return;
575:
576: case '\b':
577: case '#':
578: case '\177':
579: if (lp > str) {
580: printf("\b \b");
581: lp--;
582: }
583: continue;
584:
585: case '@':
586: case 'u'&037:
587: lp = str;
588: printf("\n\r");
589: continue;
590:
591: default:
592: if (c >= ' ' && c < '\177') {
593: if (lp < strmax) {
594: *lp++ = c;
595: printf("%c", c);
596: }
597: else {
598: printf("%c", '\007'); /* beep */
599: }
600: }
601: }
602: }
603: }
604:
605: void
606: conslog_putc(
607: char c)
608: {
609: extern unsigned int debug_mode, disableDebugOuput, disableConsoleOutput;
610:
611: if ((debug_mode && !disableDebugOuput) || !disableConsoleOutput)
612: cnputc(c);
613:
614: #ifdef MACH_BSD
615: log_putc(c);
616: #endif
617: }
618:
619: void
620: printf(const char *fmt, ...)
621: {
622: va_list listp;
623:
624: disable_preemption();
625: va_start(listp, fmt);
626: _doprnt(fmt, &listp, conslog_putc, 16);
627: va_end(listp);
628: enable_preemption();
629: }
630:
631: static char *copybyte_str;
632:
633: static void
634: copybyte(
635: char byte)
636: {
637: *copybyte_str++ = byte;
638: *copybyte_str = '\0';
639: }
640:
641: int
642: sprintf(char *buf, const char *fmt, ...)
643: {
644: va_list listp;
645: va_start(listp, fmt);
646: copybyte_str = buf;
647: _doprnt(fmt, &listp, copybyte, 16);
648: va_end(listp);
649: return strlen(buf);
650: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.