2 * (C) Copyright 2004 Texas Instruments
4 * Based on the following file:
7 * Copyright (C) 1991, 1992 Linus Torvalds
10 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
12 * Wirzenius wrote this portably, Torvalds fucked it up :-)
20 /* we use this so that we can do without the ctype library */
21 #define is_digit(c) ((c) >= '0' && (c) <= '9')
23 size_t strnlen(const char * s
, size_t count
)
27 for (sc
= s
; count
-- && *sc
!= '\0'; ++sc
)
32 static int skip_atoi(const char **s
)
37 i
= i
*10 + *((*s
)++) - '0';
41 #define ZEROPAD 1 /* pad with zero */
42 #define SIGN 2 /* unsigned/signed long */
43 #define PLUS 4 /* show plus */
44 #define SPACE 8 /* space if plus */
45 #define LEFT 16 /* left justified */
46 #define SPECIAL 32 /* 0x */
47 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
49 #define do_div(n,base) ({ \
51 __res = ((unsigned long) n) % (unsigned) base; \
52 n = ((unsigned long) n) / (unsigned) base; \
55 static char * number(char * str
, long num
, int base
, int size
, int precision
59 const char *digits
="0123456789abcdefghijklmnopqrstuvwxyz";
63 digits
= "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
66 if (base
< 2 || base
> 36)
68 c
= (type
& ZEROPAD
) ? '0' : ' ';
75 } else if (type
& PLUS
) {
78 } else if (type
& SPACE
) {
93 tmp
[i
++] = digits
[do_div(num
,base
)];
97 if (!(type
&(ZEROPAD
+LEFT
)))
102 if (type
& SPECIAL
) {
113 while (i
< precision
--)
123 static int vsprintf(char *buf
, const char *fmt
, va_list args
)
131 int flags
; /* flags to number() */
133 int field_width
; /* width of output field */
134 int precision
; /* min. # of digits for integers; max
135 number of chars for from string */
136 int qualifier
; /* 'h', 'l', or 'L' for integer fields */
138 for (str
=buf
; *fmt
; ++fmt
) {
147 ++fmt
; /* this also skips first '%' */
149 case '-': flags
|= LEFT
; goto repeat
;
150 case '+': flags
|= PLUS
; goto repeat
;
151 case ' ': flags
|= SPACE
; goto repeat
;
152 case '#': flags
|= SPECIAL
; goto repeat
;
153 case '0': flags
|= ZEROPAD
; goto repeat
;
156 /* get field width */
159 field_width
= skip_atoi(&fmt
);
160 else if (*fmt
== '*') {
162 /* it's the next argument */
163 field_width
= va_arg(args
, int);
164 if (field_width
< 0) {
165 field_width
= -field_width
;
170 /* get the precision */
175 precision
= skip_atoi(&fmt
);
176 else if (*fmt
== '*') {
178 /* it's the next argument */
179 precision
= va_arg(args
, int);
185 /* get the conversion qualifier */
187 if (*fmt
== 'h' || *fmt
== 'l' || *fmt
== 'L') {
198 while (--field_width
> 0)
200 *str
++ = (unsigned char) va_arg(args
, int);
201 while (--field_width
> 0)
206 s
= va_arg(args
, char *);
210 len
= strnlen(s
, precision
);
213 while (len
< field_width
--)
215 for (i
= 0; i
< len
; ++i
)
217 while (len
< field_width
--)
222 if (field_width
== -1) {
223 field_width
= 2*sizeof(void *);
227 (unsigned long) va_arg(args
, void *), 16,
228 field_width
, precision
, flags
);
233 if (qualifier
== 'l') {
234 long * ip
= va_arg(args
, long *);
237 int * ip
= va_arg(args
, int *);
246 /* integer number formats - set up the flags and "break" */
271 if (qualifier
== 'l')
272 num
= va_arg(args
, unsigned long);
273 else if (qualifier
== 'h') {
274 num
= (unsigned short) va_arg(args
, int);
277 } else if (flags
& SIGN
)
278 num
= va_arg(args
, int);
280 num
= va_arg(args
, unsigned int);
281 str
= number(str
, num
, base
, field_width
, precision
, flags
);
287 void serial_printf (const char *fmt
, ...)
291 char printbuffer
[CFG_PBSIZE
];
293 va_start (args
, fmt
);
295 /* For this to work, printbuffer must be larger than
296 * anything we ever want to print.
298 i
= vsprintf (printbuffer
, fmt
, args
);
301 /* Print the string */
302 serial_puts (printbuffer
);