|
|
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.