Annotation of XNU/osfmk/kern/printf.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.