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