3d6488b92b669b0b07ea4f86d4be4c6aadef4d98
2 * PROGRAMMERS: David Welch
6 * - Verify the implementation of '%Z'.
10 * linux/lib/vsprintf.c
12 * Copyright (C) 1991, 1992 Linus Torvalds
15 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
17 * Wirzenius wrote this portably, Torvalds fucked it up :-)
22 #define ZEROPAD 1 /* pad with zero */
23 #define SIGN 2 /* unsigned/signed long */
24 #define PLUS 4 /* show plus */
25 #define SPACE 8 /* space if plus */
26 #define LEFT 16 /* left justified */
27 #define SPECIAL 32 /* 0x */
28 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
29 #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;
40 /* We depend on this being true */
41 C_ASSERT(sizeof(double_t
) == sizeof(double));
48 return ( x
.exponent
== 0x7ff && ( x
.mantissah
== 0 && x
.mantissal
== 0 ));
56 return ( x
.exponent
== 0x7ff && ( x
.mantissah
!= 0 || x
.mantissal
!= 0 ));
63 do_div(long long *n
, int base
)
66 a
= ((unsigned long long) *n
) % (unsigned) base
;
67 *n
= ((unsigned long long) *n
) / (unsigned) base
;
72 static int skip_atoi(const wchar_t **s
)
77 i
= i
*10 + *((*s
)++) - L
'0';
83 number(wchar_t * buf
, wchar_t * end
, long long num
, int base
, int size
, int precision
, int type
)
85 wchar_t c
, sign
, tmp
[66];
86 const wchar_t *digits
;
87 const wchar_t *small_digits
= L
"0123456789abcdefghijklmnopqrstuvwxyz";
88 const wchar_t *large_digits
= L
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
91 digits
= (type
& LARGE
) ? large_digits
: small_digits
;
94 if (base
< 2 || base
> 36)
96 c
= (type
& ZEROPAD
) ? L
'0' : L
' ';
103 } else if (type
& PLUS
) {
106 } else if (type
& SPACE
) {
112 if ((type
& SPECIAL
) && ((type
& REMOVEHEX
) == 0)) {
117 if ((num
== 0) && (precision
!=0))
119 else while (num
!= 0)
120 tmp
[i
++] = digits
[do_div(&num
,base
)];
124 if (!(type
&(ZEROPAD
+LEFT
))) {
137 if ((type
& SPECIAL
) && ((type
& REMOVEHEX
) == 0)) {
147 if (!(type
& LEFT
)) {
154 while (i
< precision
--) {
175 numberf(wchar_t * buf
, wchar_t * end
, double_t num
, int base
, int size
, int precision
, int type
)
177 wchar_t c
, sign
, tmp
[66];
178 const wchar_t *digits
;
179 const wchar_t *small_digits
= L
"0123456789abcdefghijklmnopqrstuvwxyz";
180 const wchar_t *large_digits
= L
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
184 the float version of number is direcly copy of number
188 digits
= (type
& LARGE
) ? large_digits
: small_digits
;
191 if (base
< 2 || base
> 36)
193 c
= (type
& ZEROPAD
) ? L
'0' : L
' ';
200 } else if (type
& PLUS
) {
203 } else if (type
& SPACE
) {
208 if (type
& SPECIAL
) {
215 if (num
.AsLongLong
== 0)
217 else while (num
.AsLongLong
!= 0)
219 tmp
[i
++] = digits
[do_div(&num
.AsLongLong
,base
)];
224 if (!(type
&(ZEROPAD
+LEFT
))) {
236 if (type
& SPECIAL
) {
241 } else if (base
==16) {
250 if (!(type
& LEFT
)) {
257 while (i
< precision
--) {
276 string(wchar_t* buf
, wchar_t* end
, const char* s
, int len
, int field_width
, int precision
, int flags
)
281 c
= (flags
& ZEROPAD
) ? L
'0' : L
' ';
293 while ((unsigned int)len
< (unsigned int)precision
&& s
[len
])
298 if ((unsigned int)len
> (unsigned int)precision
)
303 while (len
< field_width
--)
309 for (i
= 0; i
< len
; ++i
)
315 while (len
< field_width
--)
325 stringw(wchar_t* buf
, wchar_t* end
, const wchar_t* sw
, int len
, int field_width
, int precision
, int flags
)
330 c
= (flags
& ZEROPAD
) ? L
'0' : L
' ';
342 while ((unsigned int)len
< (unsigned int)precision
&& sw
[len
])
347 if ((unsigned int)len
> (unsigned int)precision
)
352 while (len
< field_width
--)
358 for (i
= 0; i
< len
; ++i
)
364 while (len
< field_width
--)
376 int __cdecl
_vsnwprintf(wchar_t *buf
, size_t cnt
, const wchar_t *fmt
, va_list args
)
379 unsigned long long num
;
381 wchar_t * str
, * end
;
387 int flags
; /* flags to number() */
389 int field_width
; /* width of output field */
390 int precision
; /* min. # of digits for integers; max
391 number of chars for from string */
392 int qualifier
; /* 'h', 'l', 'L', 'w' or 'I' for integer fields */
397 end
= ((wchar_t *) -1);
401 for ( ; *fmt
; ++fmt
) {
412 ++fmt
; /* this also skips first '%' */
414 case L
'-': flags
|= LEFT
; goto repeat
;
415 case L
'+': flags
|= PLUS
; goto repeat
;
416 case L
' ': flags
|= SPACE
; goto repeat
;
417 case L
'#': flags
|= SPECIAL
; goto repeat
;
418 case L
'0': flags
|= ZEROPAD
; goto repeat
;
421 /* get field width */
424 field_width
= skip_atoi(&fmt
);
425 else if (*fmt
== L
'*') {
427 /* it's the next argument */
428 field_width
= va_arg(args
, int);
429 if (field_width
< 0) {
430 field_width
= -field_width
;
435 /* get the precision */
440 precision
= skip_atoi(&fmt
);
441 else if (*fmt
== L
'*') {
443 /* it's the next argument */
444 precision
= va_arg(args
, int);
450 /* get the conversion qualifier */
452 if (*fmt
== L
'l' && *(fmt
+1) == L
'l') {
455 } else if (*fmt
== L
'h' || *fmt
== L
'l' || *fmt
== L
'L' || *fmt
== L
'w') {
458 } else if (*fmt
== L
'I' && *(fmt
+1) == L
'6' && *(fmt
+2) == L
'4') {
461 } else if (*fmt
== L
'I' && *(fmt
+1) == L
'3' && *(fmt
+2) == L
'2') {
464 } else if (*fmt
== L
'F' && *(fmt
+1) == L
'p') {
474 if (qualifier
== 'h' || qualifier
== 'w') {
476 /* print unicode string */
477 sw1
[0] = (wchar_t) va_arg(args
, int);
479 str
= stringw(str
, end
, (wchar_t *)&sw1
, -1, field_width
, precision
, flags
);
482 /* print ascii string */
483 s1
[0] = ( unsigned char) va_arg(args
, int);
485 str
= string(str
, end
, (char *)&s1
, -1, field_width
, precision
, flags
);
492 while (--field_width
> 0) {
497 if (qualifier
== 'l' || qualifier
== 'w') {
499 *str
= (wchar_t) va_arg(args
, int);
503 *str
= (wchar_t) va_arg(args
, int);
506 while (--field_width
> 0) {
514 if (qualifier
== 'h') {
515 /* print ascii string */
516 s
= va_arg(args
, char *);
517 str
= string(str
, end
, s
, -1, field_width
, precision
, flags
);
519 /* print unicode string */
520 sw
= va_arg(args
, wchar_t *);
521 str
= stringw(str
, end
, sw
, -1, field_width
, precision
, flags
);
526 if (qualifier
== 'l' || qualifier
== 'w') {
527 /* print unicode string */
528 sw
= va_arg(args
, wchar_t *);
529 str
= stringw(str
, end
, sw
, -1, field_width
, precision
, flags
);
531 /* print ascii string */
532 s
= va_arg(args
, char *);
533 str
= string(str
, end
, s
, -1, field_width
, precision
, flags
);
538 if (qualifier
== 'h') {
539 /* print counted ascii string */
540 PANSI_STRING pus
= va_arg(args
, PANSI_STRING
);
541 if ((pus
== NULL
) || (pus
->Buffer
== NULL
)) {
548 str
= string(str
, end
, s
, len
, field_width
, precision
, flags
);
550 /* print counted unicode string */
551 PUNICODE_STRING pus
= va_arg(args
, PUNICODE_STRING
);
552 if ((pus
== NULL
) || (pus
->Buffer
== NULL
)) {
557 len
= pus
->Length
/ sizeof(WCHAR
);
559 str
= stringw(str
, end
, sw
, len
, field_width
, precision
, flags
);
564 if ((flags
& LARGE
) == 0)
566 if (field_width
== -1) {
567 field_width
= 2*sizeof(void *);
570 str
= number(str
, end
,
571 (ULONG_PTR
) va_arg(args
, void *), 16,
572 field_width
, precision
, flags
);
576 /* FIXME: What does C99 say about the overflow case here? */
577 if (qualifier
== 'l') {
578 long * ip
= va_arg(args
, long *);
581 int * ip
= va_arg(args
, int *);
585 /* float number formats - set up the flags and "break" */
591 _double
= va_arg(args
, double_t
);
593 if ( _isnan(_double
) ) {
602 } else if ( _isinf(_double
) < 0 ) {
611 } else if ( _isinf(_double
) > 0 ) {
621 if ( precision
== -1 )
623 str
= numberf(str
, end
, _double
, base
, field_width
, precision
, flags
);
630 /* integer number formats - set up the flags and "break" */
661 if (qualifier
== L
'I')
662 num
= va_arg(args
, unsigned long long);
663 else if (qualifier
== L
'l') {
665 num
= va_arg(args
, long);
667 num
= va_arg(args
, unsigned long);
669 else if (qualifier
== L
'h') {
671 num
= va_arg(args
, int);
673 num
= va_arg(args
, unsigned int);
677 num
= va_arg(args
, int);
679 num
= va_arg(args
, unsigned int);
681 str
= number(str
, end
, num
, base
, field_width
, precision
, flags
);
686 /* don't write out a null byte if the buf size is zero */
695 int swprintf(wchar_t *buf
, const wchar_t *fmt
, ...)
701 i
=_vsnwprintf(buf
,MAXLONG
,fmt
,args
);
710 int __cdecl
_snwprintf(wchar_t *buf
, size_t cnt
, const wchar_t *fmt
, ...)
716 i
=_vsnwprintf(buf
,cnt
,fmt
,args
);
725 int __cdecl
vswprintf(wchar_t *buf
, const wchar_t *fmt
, va_list args
)
727 return _vsnwprintf(buf
,MAXLONG
,fmt
,args
);