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
hex2asc(int n)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
xputs(const char * s,void (* xputc)(unsigned n,void * cookie),void * cookie)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
__xprintf(const char * fmt,va_list ap,void (* xputc)(unsigned n,void * cookie),void * cookie)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