4 * Copyright (C) 1991, 1992 Linus Torvalds
7 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
9 * Wirzenius wrote this portably, Torvalds fucked it up :-)
16 /* we use this so that we can do without the ctype library */
17 #define is_digit(c) ((c) >= '0' && (c) <= '9')
19 static int skip_atoi(const char **s
)
24 i
= i
*10 + *((*s
)++) - '0';
28 #define ZEROPAD 1 /* pad with zero */
29 #define SIGN 2 /* unsigned/signed long */
30 #define PLUS 4 /* show plus */
31 #define SPACE 8 /* space if plus */
32 #define LEFT 16 /* left justified */
33 #define SPECIAL 32 /* 0x */
34 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
36 #define do_div(n,base) ({ \
38 __res = ((unsigned long) n) % (unsigned) base; \
39 n = ((unsigned long) n) / (unsigned) base; \
42 static char * number(char * str
, long num
, int base
, int size
, int precision
46 const char *digits
="0123456789abcdefghijklmnopqrstuvwxyz";
50 digits
= "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
53 if (base
< 2 || base
> 36)
55 c
= (type
& ZEROPAD
) ? '0' : ' ';
62 } else if (type
& PLUS
) {
65 } else if (type
& SPACE
) {
80 tmp
[i
++] = digits
[do_div(num
,base
)];
84 if (!(type
&(ZEROPAD
+LEFT
)))
100 while (i
< precision
--)
109 int kvsprintf(char *buf
, const char *fmt
, va_list args
)
117 int flags
; /* flags to number() */
119 int field_width
; /* width of output field */
120 int precision
; /* min. # of digits for integers; max
121 number of chars for from string */
122 int qualifier
; /* 'h', 'l', or 'L' for integer fields */
124 for (str
=buf
; *fmt
; ++fmt
) {
133 ++fmt
; /* this also skips first '%' */
135 case '-': flags
|= LEFT
; goto repeat
;
136 case '+': flags
|= PLUS
; goto repeat
;
137 case ' ': flags
|= SPACE
; goto repeat
;
138 case '#': flags
|= SPECIAL
; goto repeat
;
139 case '0': flags
|= ZEROPAD
; goto repeat
;
142 /* get field width */
145 field_width
= skip_atoi(&fmt
);
146 else if (*fmt
== '*') {
148 /* it's the next argument */
149 field_width
= va_arg(args
, int);
150 if (field_width
< 0) {
151 field_width
= -field_width
;
156 /* get the precision */
161 precision
= skip_atoi(&fmt
);
162 else if (*fmt
== '*') {
164 /* it's the next argument */
165 precision
= va_arg(args
, int);
171 /* get the conversion qualifier */
173 if (*fmt
== 'h' || *fmt
== 'l' || *fmt
== 'L') {
184 while (--field_width
> 0)
186 *str
++ = (unsigned char) va_arg(args
, int);
187 while (--field_width
> 0)
192 s
= va_arg(args
, char *);
196 len
= strnlen(s
, precision
);
199 while (len
< field_width
--)
201 for (i
= 0; i
< len
; ++i
)
203 while (len
< field_width
--)
208 if (field_width
== -1) {
209 field_width
= 2*sizeof(void *);
213 (unsigned long) va_arg(args
, void *), 16,
214 field_width
, precision
, flags
);
219 if (qualifier
== 'l') {
220 long * ip
= va_arg(args
, long *);
223 int * ip
= va_arg(args
, int *);
232 /* integer number formats - set up the flags and "break" */
257 if (qualifier
== 'l')
258 num
= va_arg(args
, unsigned long);
259 else if (qualifier
== 'h') {
260 num
= (unsigned short) va_arg(args
, int);
263 } else if (flags
& SIGN
)
264 num
= va_arg(args
, int);
266 num
= va_arg(args
, unsigned int);
267 str
= number(str
, num
, base
, field_width
, precision
, flags
);
273 #define __DOUTBUFSIZE 256
275 char __outstr
[__DOUTBUFSIZE
];
277 //---------------------------------------------------------------------------------
278 void kprintf(const char *str
, ...)
279 //---------------------------------------------------------------------------------
287 len
=kvsprintf(__outstr
,str
,args
);
290 write(2, __outstr
, len
);