4 * Copyright (C) 1991, 1992 Linus Torvalds
9 #include <console/vtxprintf.h>
11 /* haha, don't need ctype.c */
12 #define isdigit(c) ((c) >= '0' && (c) <= '9')
13 #define is_digit isdigit
14 #define isxdigit(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
16 static int skip_atoi(const char **s
)
21 i
= i
*10 + *((*s
)++) - '0';
25 #define ZEROPAD 1 /* pad with zero */
26 #define SIGN 2 /* unsigned/signed long */
27 #define PLUS 4 /* show plus */
28 #define SPACE 8 /* space if plus */
29 #define LEFT 16 /* left justified */
30 #define SPECIAL 32 /* 0x */
31 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
33 static int number(void (*tx_byte
)(unsigned char byte
),
34 unsigned long long num
, int base
, int size
, int precision
, int type
)
37 const char *digits
="0123456789abcdefghijklmnopqrstuvwxyz";
42 digits
= "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
45 if (base
< 2 || base
> 36)
47 c
= (type
& ZEROPAD
) ? '0' : ' ';
50 if ((signed long long)num
< 0) {
54 } else if (type
& PLUS
) {
57 } else if (type
& SPACE
) {
72 tmp
[i
++] = digits
[do_div(num
,base
)];
76 if (!(type
&(ZEROPAD
+LEFT
)))
78 tx_byte(' '), count
++;
80 tx_byte(sign
), count
++;
83 tx_byte('0'), count
++;
85 tx_byte('0'), count
++;
86 tx_byte(digits
[33]), count
++;
92 while (i
< precision
--)
93 tx_byte('0'), count
++;
95 tx_byte(tmp
[i
]), count
++;
97 tx_byte(' '), count
++;
102 int vtxprintf(void (*tx_byte
)(unsigned char byte
), const char *fmt
, va_list args
)
105 unsigned long long num
;
109 int flags
; /* flags to number() */
111 int field_width
; /* width of output field */
112 int precision
; /* min. # of digits for integers; max
113 number of chars for from string */
114 int qualifier
; /* 'h', 'l', or 'L' for integer fields */
118 for (count
=0; *fmt
; ++fmt
) {
120 tx_byte(*fmt
), count
++;
127 ++fmt
; /* this also skips first '%' */
129 case '-': flags
|= LEFT
; goto repeat
;
130 case '+': flags
|= PLUS
; goto repeat
;
131 case ' ': flags
|= SPACE
; goto repeat
;
132 case '#': flags
|= SPECIAL
; goto repeat
;
133 case '0': flags
|= ZEROPAD
; goto repeat
;
136 /* get field width */
139 field_width
= skip_atoi(&fmt
);
140 else if (*fmt
== '*') {
142 /* it's the next argument */
143 field_width
= va_arg(args
, int);
144 if (field_width
< 0) {
145 field_width
= -field_width
;
150 /* get the precision */
155 precision
= skip_atoi(&fmt
);
156 else if (*fmt
== '*') {
158 /* it's the next argument */
159 precision
= va_arg(args
, int);
165 /* get the conversion qualifier */
167 if (*fmt
== 'h' || *fmt
== 'l' || *fmt
== 'L') {
182 while (--field_width
> 0)
183 tx_byte(' '), count
++;
184 tx_byte((unsigned char) va_arg(args
, int)), count
++;
185 while (--field_width
> 0)
186 tx_byte(' '), count
++;
190 s
= va_arg(args
, char *);
194 len
= strnlen(s
, precision
);
197 while (len
< field_width
--)
198 tx_byte(' '), count
++;
199 for (i
= 0; i
< len
; ++i
)
200 tx_byte(*s
++), count
++;
201 while (len
< field_width
--)
202 tx_byte(' '), count
++;
206 if (field_width
== -1) {
207 field_width
= 2*sizeof(void *);
210 count
+= number(tx_byte
,
211 (unsigned long) va_arg(args
, void *), 16,
212 field_width
, precision
, flags
);
217 if (qualifier
== 'L') {
218 long long *ip
= va_arg(args
, long long *);
220 } else if (qualifier
== 'l') {
221 long * ip
= va_arg(args
, long *);
224 int * ip
= va_arg(args
, int *);
230 tx_byte('%'), count
++;
233 /* integer number formats - set up the flags and "break" */
251 tx_byte('%'), count
++;
253 tx_byte(*fmt
), count
++;
258 if (qualifier
== 'L') {
259 num
= va_arg(args
, unsigned long long);
260 } else if (qualifier
== 'l') {
261 num
= va_arg(args
, unsigned long);
262 } else if (qualifier
== 'h') {
263 num
= (unsigned short) va_arg(args
, int);
266 } else if (flags
& SIGN
) {
267 num
= va_arg(args
, int);
269 num
= va_arg(args
, unsigned int);
271 count
+= number(tx_byte
, num
, base
, field_width
, precision
, flags
);