Home | History | Annotate | Download | only in libc
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *  * Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  *  * Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in
     12  *    the documentation and/or other materials provided with the
     13  *    distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
     22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <stdarg.h>
     30 #include "libc_private.h"
     31 
     32 static int hex2asc(int n)
     33 {
     34     n &= 15;
     35     if(n > 9){
     36         return ('a' - 10) + n;
     37     } else {
     38         return '0' + n;
     39     }
     40 }
     41 
     42 static void xputs(const char *s, void (*xputc)(unsigned n, void *cookie), void *cookie)
     43 {
     44     while (*s) {
     45         xputc(*s++, cookie);
     46     }
     47 }
     48 
     49 void __xprintf(const char *fmt, va_list ap,
     50                void (*xputc)(unsigned n, void *cookie),
     51                void *cookie)
     52 {
     53     char scratch[16];
     54 
     55     for(;;){
     56         switch(*fmt){
     57         case 0:
     58             va_end(ap);
     59             return;
     60         case '%':
     61             switch(fmt[1]) {
     62             case 'c': {
     63                 unsigned n = va_arg(ap, unsigned);
     64                 xputc(n, cookie);
     65                 fmt += 2;
     66                 continue;
     67             }
     68             case 'h': {
     69                 unsigned n = va_arg(ap, unsigned);
     70                 xputc(hex2asc(n >> 12), cookie);
     71                 xputc(hex2asc(n >> 8), cookie);
     72                 xputc(hex2asc(n >> 4), cookie);
     73                 xputc(hex2asc(n >> 0), cookie);
     74                 fmt += 2;
     75                 continue;
     76             }
     77             case 'b': {
     78                 unsigned n = va_arg(ap, unsigned);
     79                 xputc(hex2asc(n >> 4), cookie);
     80                 xputc(hex2asc(n >> 0), cookie);
     81                 fmt += 2;
     82                 continue;
     83             }
     84             case 'p':
     85             case 'X':
     86             case 'x': {
     87                 unsigned n = va_arg(ap, unsigned);
     88                 char *p = scratch + 15;
     89                 *p = 0;
     90                 do {
     91                     *--p = hex2asc(n);
     92                     n = n >> 4;
     93                 } while(n != 0);
     94                 while(p > (scratch + 7)) *--p = '0';
     95                 xputs(p, xputc, cookie);
     96                 fmt += 2;
     97                 continue;
     98             }
     99             case 'd': {
    100                 int n = va_arg(ap, int);
    101                 char *p = scratch + 15;
    102                 *p = 0;
    103                 if(n < 0) {
    104                     xputc('-', cookie);
    105                     n = -n;
    106                 }
    107                 do {
    108                     *--p = (n % 10) + '0';
    109                     n /= 10;
    110                 } while(n != 0);
    111                 xputs(p, xputc, cookie);
    112                 fmt += 2;
    113                 continue;
    114             }
    115             case 's': {
    116                 char *s = va_arg(ap, char*);
    117                 if(s == 0) s = "(null)";
    118                 xputs(s, xputc, cookie);
    119                 fmt += 2;
    120                 continue;
    121             }
    122             }
    123             xputc(*fmt++, cookie);
    124             break;
    125         case '\n':
    126             xputc('\r', cookie);
    127         default:
    128             xputc(*fmt++, cookie);
    129         }
    130     }
    131 }
    132