1 #ifndef USE_NEW_SPRINTF
3 * PROGRAMMERS: David Welch
7 * - Verify the implementation of '%Z'.
11 * linux/lib/vsprintf.c
13 * Copyright (C) 1991, 1992 Linus Torvalds
16 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
18 * Wirzenius wrote this portably, Torvalds fucked it up :-)
23 #define ZEROPAD 1 /* pad with zero */
24 #define SIGN 2 /* unsigned/signed long */
25 #define PLUS 4 /* show plus */
26 #define SPACE 8 /* space if plus */
27 #define LEFT 16 /* left justified */
28 #define SPECIAL 32 /* 0x */
29 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
30 #define REMOVEHEX 256 /* use 256 as remve 0x frim BASE 16 */
32 unsigned int mantissal
:32;
33 unsigned int mantissah
:20;
34 unsigned int exponent
:11;
50 return ( x
.x
->exponent
== 0x7ff && ( x
.x
->mantissah
== 0 && x
.x
->mantissal
== 0 ));
64 return ( x
.x
->exponent
== 0x7ff && ( x
.x
->mantissah
!= 0 || x
.x
->mantissal
!= 0 ));
71 do_div(long long *n
, int base
)
74 a
= ((unsigned long long) *n
) % (unsigned) base
;
75 *n
= ((unsigned long long) *n
) / (unsigned) base
;
80 static int skip_atoi(const wchar_t **s
)
85 i
= i
*10 + *((*s
)++) - L
'0';
91 number(wchar_t * buf
, wchar_t * end
, long long num
, int base
, int size
, int precision
, int type
)
93 wchar_t c
, sign
, tmp
[66];
94 const wchar_t *digits
;
95 const wchar_t *small_digits
= L
"0123456789abcdefghijklmnopqrstuvwxyz";
96 const wchar_t *large_digits
= L
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
99 digits
= (type
& LARGE
) ? large_digits
: small_digits
;
102 if (base
< 2 || base
> 36)
104 c
= (type
& ZEROPAD
) ? L
'0' : L
' ';
111 } else if (type
& PLUS
) {
114 } else if (type
& SPACE
) {
120 if ((type
& SPECIAL
) && ((type
& REMOVEHEX
) == 0)) {
125 if ((num
== 0) && (precision
!=0))
127 else while (num
!= 0)
128 tmp
[i
++] = digits
[do_div(&num
,base
)];
132 if (!(type
&(ZEROPAD
+LEFT
))) {
145 if ((type
& SPECIAL
) && ((type
& REMOVEHEX
) == 0)) {
155 if (!(type
& LEFT
)) {
162 while (i
< precision
--) {
183 numberf(wchar_t * buf
, wchar_t * end
, double num
, int base
, int size
, int precision
, int type
)
185 wchar_t c
, sign
, tmp
[66];
186 const wchar_t *digits
;
187 const wchar_t *small_digits
= L
"0123456789abcdefghijklmnopqrstuvwxyz";
188 const wchar_t *large_digits
= L
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
193 the float version of number is direcly copy of number
197 digits
= (type
& LARGE
) ? large_digits
: small_digits
;
200 if (base
< 2 || base
> 36)
202 c
= (type
& ZEROPAD
) ? L
'0' : L
' ';
209 } else if (type
& PLUS
) {
212 } else if (type
& SPACE
) {
217 if (type
& SPECIAL
) {
226 else while (num
!= 0)
229 tmp
[i
++] = digits
[do_div(&x
,base
)];
230 #ifndef _M_ARM // Missing __floatdidf in CeGCC 0.55 -- GCC 4.4
237 if (!(type
&(ZEROPAD
+LEFT
))) {
249 if (type
& SPECIAL
) {
254 } else if (base
==16) {
263 if (!(type
& LEFT
)) {
270 while (i
< precision
--) {
289 string(wchar_t* buf
, wchar_t* end
, const char* s
, int len
, int field_width
, int precision
, int flags
)
294 c
= (flags
& ZEROPAD
) ? L
'0' : L
' ';
306 while ((unsigned int)len
< (unsigned int)precision
&& s
[len
])
311 if ((unsigned int)len
> (unsigned int)precision
)
316 while (len
< field_width
--)
322 for (i
= 0; i
< len
; ++i
)
328 while (len
< field_width
--)
338 stringw(wchar_t* buf
, wchar_t* end
, const wchar_t* sw
, int len
, int field_width
, int precision
, int flags
)
343 c
= (flags
& ZEROPAD
) ? L
'0' : L
' ';
355 while ((unsigned int)len
< (unsigned int)precision
&& sw
[len
])
360 if ((unsigned int)len
> (unsigned int)precision
)
365 while (len
< field_width
--)
371 for (i
= 0; i
< len
; ++i
)
377 while (len
< field_width
--)
389 int __cdecl
_vsnwprintf(wchar_t *buf
, size_t cnt
, const wchar_t *fmt
, va_list args
)
392 unsigned long long num
;
394 wchar_t * str
, * end
;
400 int flags
; /* flags to number() */
402 int field_width
; /* width of output field */
403 int precision
; /* min. # of digits for integers; max
404 number of chars for from string */
405 int qualifier
; /* 'h', 'l', 'L', 'w' or 'I' for integer fields */
410 end
= ((wchar_t *) -1);
414 for ( ; *fmt
; ++fmt
) {
425 ++fmt
; /* this also skips first '%' */
427 case L
'-': flags
|= LEFT
; goto repeat
;
428 case L
'+': flags
|= PLUS
; goto repeat
;
429 case L
' ': flags
|= SPACE
; goto repeat
;
430 case L
'#': flags
|= SPECIAL
; goto repeat
;
431 case L
'0': flags
|= ZEROPAD
; goto repeat
;
434 /* get field width */
437 field_width
= skip_atoi(&fmt
);
438 else if (*fmt
== L
'*') {
440 /* it's the next argument */
441 field_width
= va_arg(args
, int);
442 if (field_width
< 0) {
443 field_width
= -field_width
;
448 /* get the precision */
453 precision
= skip_atoi(&fmt
);
454 else if (*fmt
== L
'*') {
456 /* it's the next argument */
457 precision
= va_arg(args
, int);
463 /* get the conversion qualifier */
465 if (*fmt
== L
'l' && *(fmt
+1) == L
'l') {
468 } else if (*fmt
== L
'h' || *fmt
== L
'l' || *fmt
== L
'L' || *fmt
== L
'w') {
471 } else if (*fmt
== L
'I' && *(fmt
+1) == L
'6' && *(fmt
+2) == L
'4') {
474 } else if (*fmt
== L
'I' && *(fmt
+1) == L
'3' && *(fmt
+2) == L
'2') {
477 } else if (*fmt
== L
'F' && *(fmt
+1) == L
'p') {
487 if (qualifier
== 'h' || qualifier
== 'w') {
489 /* print unicode string */
490 sw1
[0] = (wchar_t) va_arg(args
, int);
492 str
= stringw(str
, end
, (wchar_t *)&sw1
, -1, field_width
, precision
, flags
);
495 /* print ascii string */
496 s1
[0] = ( unsigned char) va_arg(args
, int);
498 str
= string(str
, end
, (char *)&s1
, -1, field_width
, precision
, flags
);
505 while (--field_width
> 0) {
510 if (qualifier
== 'l' || qualifier
== 'w') {
512 *str
= (wchar_t) va_arg(args
, int);
516 *str
= (wchar_t) va_arg(args
, int);
519 while (--field_width
> 0) {
527 if (qualifier
== 'h') {
528 /* print ascii string */
529 s
= va_arg(args
, char *);
530 str
= string(str
, end
, s
, -1, field_width
, precision
, flags
);
532 /* print unicode string */
533 sw
= va_arg(args
, wchar_t *);
534 str
= stringw(str
, end
, sw
, -1, field_width
, precision
, flags
);
539 if (qualifier
== 'l' || qualifier
== 'w') {
540 /* print unicode string */
541 sw
= va_arg(args
, wchar_t *);
542 str
= stringw(str
, end
, sw
, -1, field_width
, precision
, flags
);
544 /* print ascii string */
545 s
= va_arg(args
, char *);
546 str
= string(str
, end
, s
, -1, field_width
, precision
, flags
);
551 if (qualifier
== 'h') {
552 /* print counted ascii string */
553 PANSI_STRING pus
= va_arg(args
, PANSI_STRING
);
554 if ((pus
== NULL
) || (pus
->Buffer
== NULL
)) {
561 str
= string(str
, end
, s
, len
, field_width
, precision
, flags
);
563 /* print counted unicode string */
564 PUNICODE_STRING pus
= va_arg(args
, PUNICODE_STRING
);
565 if ((pus
== NULL
) || (pus
->Buffer
== NULL
)) {
570 len
= pus
->Length
/ sizeof(WCHAR
);
572 str
= stringw(str
, end
, sw
, len
, field_width
, precision
, flags
);
577 if ((flags
& LARGE
) == 0)
579 if (field_width
== -1) {
580 field_width
= 2*sizeof(void *);
583 str
= number(str
, end
,
584 (ULONG_PTR
) va_arg(args
, void *), 16,
585 field_width
, precision
, flags
);
589 /* FIXME: What does C99 say about the overflow case here? */
590 if (qualifier
== 'l') {
591 long * ip
= va_arg(args
, long *);
594 int * ip
= va_arg(args
, int *);
598 /* float number formats - set up the flags and "break" */
604 _double
= (double)va_arg(args
, double);
606 if ( _isnan(_double
) ) {
615 } else if ( _isinf(_double
) < 0 ) {
624 } else if ( _isinf(_double
) > 0 ) {
634 if ( precision
== -1 )
636 str
= numberf(str
, end
, _double
, base
, field_width
, precision
, flags
);
643 /* integer number formats - set up the flags and "break" */
674 if (qualifier
== L
'I')
675 num
= va_arg(args
, unsigned long long);
676 else if (qualifier
== L
'l') {
678 num
= va_arg(args
, long);
680 num
= va_arg(args
, unsigned long);
682 else if (qualifier
== L
'h') {
684 num
= va_arg(args
, int);
686 num
= va_arg(args
, unsigned int);
690 num
= va_arg(args
, int);
692 num
= va_arg(args
, unsigned int);
694 str
= number(str
, end
, num
, base
, field_width
, precision
, flags
);
699 /* don't write out a null byte if the buf size is zero */
708 int swprintf(wchar_t *buf
, const wchar_t *fmt
, ...)
714 i
=_vsnwprintf(buf
,MAXLONG
,fmt
,args
);
723 int __cdecl
_snwprintf(wchar_t *buf
, size_t cnt
, const wchar_t *fmt
, ...)
729 i
=_vsnwprintf(buf
,cnt
,fmt
,args
);
738 int __cdecl
vswprintf(wchar_t *buf
, const wchar_t *fmt
, va_list args
)
740 return _vsnwprintf(buf
,MAXLONG
,fmt
,args
);