7
7
* ----------------------------------------------------------------------- */
8
8
9
9
/*
10
- * Oh, it's a waste of space, but oh-so-yummy for debugging. This
11
- * version of printf() does not include 64-bit support. "Live with
12
- * it."
13
- *
10
+ * Oh, it's a waste of space, but oh-so-yummy for debugging.
14
11
*/
15
12
16
13
#include <stdarg.h>
@@ -28,6 +25,86 @@ static int skip_atoi(const char **s)
28
25
return i ;
29
26
}
30
27
28
+ /*
29
+ * put_dec_full4 handles numbers in the range 0 <= r < 10000.
30
+ * The multiplier 0xccd is round(2^15/10), and the approximation
31
+ * r/10 == (r * 0xccd) >> 15 is exact for all r < 16389.
32
+ */
33
+ static
34
+ void put_dec_full4 (char * buf , unsigned int r )
35
+ {
36
+ int i ;
37
+
38
+ for (i = 0 ; i < 3 ; i ++ ) {
39
+ unsigned int q = (r * 0xccd ) >> 15 ;
40
+ * buf ++ = '0' + (r - q * 10 );
41
+ r = q ;
42
+ }
43
+ * buf ++ = '0' + r ;
44
+ }
45
+
46
+ /* put_dec is copied from lib/vsprintf.c with small modifications */
47
+
48
+ /*
49
+ * Call put_dec_full4 on x % 10000, return x / 10000.
50
+ * The approximation x/10000 == (x * 0x346DC5D7) >> 43
51
+ * holds for all x < 1,128,869,999. The largest value this
52
+ * helper will ever be asked to convert is 1,125,520,955.
53
+ * (second call in the put_dec code, assuming n is all-ones).
54
+ */
55
+ static
56
+ unsigned int put_dec_helper4 (char * buf , unsigned int x )
57
+ {
58
+ unsigned int q = (x * 0x346DC5D7ULL ) >> 43 ;
59
+
60
+ put_dec_full4 (buf , x - q * 10000 );
61
+ return q ;
62
+ }
63
+
64
+ /* Based on code by Douglas W. Jones found at
65
+ * <http://www.cs.uiowa.edu/~jones/bcd/decimal.html#sixtyfour>
66
+ * (with permission from the author).
67
+ * Performs no 64-bit division and hence should be fast on 32-bit machines.
68
+ */
69
+ static
70
+ int put_dec (char * buf , unsigned long long n )
71
+ {
72
+ unsigned int d3 , d2 , d1 , q , h ;
73
+ char * p = buf ;
74
+
75
+ d1 = ((unsigned int )n >> 16 ); /* implicit "& 0xffff" */
76
+ h = (n >> 32 );
77
+ d2 = (h ) & 0xffff ;
78
+ d3 = (h >> 16 ); /* implicit "& 0xffff" */
79
+
80
+ /* n = 2^48 d3 + 2^32 d2 + 2^16 d1 + d0
81
+ = 281_4749_7671_0656 d3 + 42_9496_7296 d2 + 6_5536 d1 + d0 */
82
+ q = 656 * d3 + 7296 * d2 + 5536 * d1 + ((unsigned int )n & 0xffff );
83
+ q = put_dec_helper4 (p , q );
84
+ p += 4 ;
85
+
86
+ q += 7671 * d3 + 9496 * d2 + 6 * d1 ;
87
+ q = put_dec_helper4 (p , q );
88
+ p += 4 ;
89
+
90
+ q += 4749 * d3 + 42 * d2 ;
91
+ q = put_dec_helper4 (p , q );
92
+ p += 4 ;
93
+
94
+ q += 281 * d3 ;
95
+ q = put_dec_helper4 (p , q );
96
+ p += 4 ;
97
+
98
+ put_dec_full4 (p , q );
99
+ p += 4 ;
100
+
101
+ /* strip off the extra 0's we printed */
102
+ while (p > buf && p [-1 ] == '0' )
103
+ -- p ;
104
+
105
+ return p - buf ;
106
+ }
107
+
31
108
#define ZEROPAD 1 /* pad with zero */
32
109
#define SIGN 2 /* unsigned/signed long */
33
110
#define PLUS 4 /* show plus */
@@ -36,13 +113,7 @@ static int skip_atoi(const char **s)
36
113
#define SMALL 32 /* Must be 32 == 0x20 */
37
114
#define SPECIAL 64 /* 0x */
38
115
39
- #define __do_div (n , base ) ({ \
40
- int __res; \
41
- __res = ((unsigned long) n) % (unsigned) base; \
42
- n = ((unsigned long) n) / (unsigned) base; \
43
- __res; })
44
-
45
- static char * number (char * str , long num , int base , int size , int precision ,
116
+ static char * number (char * str , long long num , int base , int size , int precision ,
46
117
int type )
47
118
{
48
119
/* we are called with base 8, 10 or 16, only, thus don't need "G..." */
@@ -57,8 +128,6 @@ static char *number(char *str, long num, int base, int size, int precision,
57
128
locase = (type & SMALL );
58
129
if (type & LEFT )
59
130
type &= ~ZEROPAD ;
60
- if (base < 2 || base > 16 )
61
- return NULL ;
62
131
c = (type & ZEROPAD ) ? '0' : ' ' ;
63
132
sign = 0 ;
64
133
if (type & SIGN ) {
@@ -83,9 +152,28 @@ static char *number(char *str, long num, int base, int size, int precision,
83
152
i = 0 ;
84
153
if (num == 0 )
85
154
tmp [i ++ ] = '0' ;
86
- else
87
- while (num != 0 )
88
- tmp [i ++ ] = (digits [__do_div (num , base )] | locase );
155
+ else {
156
+ switch (base ) {
157
+ case 10 :
158
+ i += put_dec (& tmp [i ], num );
159
+ break ;
160
+ case 8 :
161
+ while (num != 0 ) {
162
+ tmp [i ++ ] = '0' + (num & 07 );
163
+ num = (unsigned long long )num >> 3 ;
164
+ }
165
+ break ;
166
+ case 16 :
167
+ while (num != 0 ) {
168
+ tmp [i ++ ] = digits [num & 0xf ] | locase ;
169
+ num = (unsigned long long )num >> 4 ;
170
+ }
171
+ break ;
172
+ default :
173
+ unreachable ();
174
+ }
175
+ }
176
+
89
177
if (i > precision )
90
178
precision = i ;
91
179
size -= precision ;
@@ -117,7 +205,7 @@ static char *number(char *str, long num, int base, int size, int precision,
117
205
int vsprintf (char * buf , const char * fmt , va_list args )
118
206
{
119
207
int len ;
120
- unsigned long num ;
208
+ unsigned long long num ;
121
209
int i , base ;
122
210
char * str ;
123
211
const char * s ;
@@ -127,7 +215,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
127
215
int field_width ; /* width of output field */
128
216
int precision ; /* min. # of digits for integers; max
129
217
number of chars for from string */
130
- int qualifier ; /* 'h' or 'l' for integer fields */
218
+ int qualifier ; /* 'h', 'hh', 'l' or 'll ' for integer fields */
131
219
132
220
for (str = buf ; * fmt ; ++ fmt ) {
133
221
if (* fmt != '%' ) {
@@ -191,6 +279,10 @@ int vsprintf(char *buf, const char *fmt, va_list args)
191
279
if (* fmt == 'h' || * fmt == 'l' ) {
192
280
qualifier = * fmt ;
193
281
++ fmt ;
282
+ if (qualifier == * fmt ) {
283
+ qualifier -= 'a' - 'A' ;
284
+ ++ fmt ;
285
+ }
194
286
}
195
287
196
288
/* default base */
@@ -260,16 +352,40 @@ int vsprintf(char *buf, const char *fmt, va_list args)
260
352
-- fmt ;
261
353
continue ;
262
354
}
263
- if (qualifier == 'l' ) {
264
- num = va_arg (args , unsigned long );
265
- } else if (qualifier == 'h' ) {
266
- num = (unsigned short )va_arg (args , int );
267
- if (flags & SIGN )
268
- num = (short )num ;
269
- } else if (flags & SIGN ) {
270
- num = va_arg (args , int );
355
+ if (flags & SIGN ) {
356
+ switch (qualifier ) {
357
+ case 'L' :
358
+ num = va_arg (args , long long );
359
+ break ;
360
+ case 'l' :
361
+ num = va_arg (args , long );
362
+ break ;
363
+ case 'h' :
364
+ num = (short )va_arg (args , int );
365
+ break ;
366
+ case 'H' :
367
+ num = (signed char )va_arg (args , int );
368
+ break ;
369
+ default :
370
+ num = va_arg (args , int );
371
+ }
271
372
} else {
272
- num = va_arg (args , unsigned int );
373
+ switch (qualifier ) {
374
+ case 'L' :
375
+ num = va_arg (args , unsigned long long);
376
+ break ;
377
+ case 'l' :
378
+ num = va_arg (args , unsigned long );
379
+ break ;
380
+ case 'h' :
381
+ num = (unsigned short )va_arg (args , int );
382
+ break ;
383
+ case 'H' :
384
+ num = (unsigned char )va_arg (args , int );
385
+ break ;
386
+ default :
387
+ num = va_arg (args , unsigned int );
388
+ }
273
389
}
274
390
str = number (str , num , base , field_width , precision , flags );
275
391
}
0 commit comments