51461147d0a625f69e376f93560a321870ffd023
2 #ifndef USE_NEW_SPRINTF
4 * PROGRAMMERS: David Welch
8 * - Verify the implementation of '%Z'.
12 * linux/lib/vsprintf.c
14 * Copyright (C) 1991, 1992 Linus Torvalds
17 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
19 * Wirzenius wrote this portably, Torvalds fucked it up :-)
24 #define ZEROPAD 1 /* pad with zero */
25 #define SIGN 2 /* unsigned/signed long */
26 #define PLUS 4 /* show plus */
27 #define SPACE 8 /* space if plus */
28 #define LEFT 16 /* left justified */
29 #define SPECIAL 32 /* 0x */
30 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
31 #define REMOVEHEX 256 /* use 256 as remve 0x frim BASE 16 */
33 unsigned int mantissal
:32;
34 unsigned int mantissah
:20;
35 unsigned int exponent
:11;
51 return ( x
.x
->exponent
== 0x7ff && ( x
.x
->mantissah
== 0 && x
.x
->mantissal
== 0 ));
65 return ( x
.x
->exponent
== 0x7ff && ( x
.x
->mantissah
!= 0 || x
.x
->mantissal
!= 0 ));
72 do_div(long long *n
, int base
)
75 a
= ((unsigned long long) *n
) % (unsigned) base
;
76 *n
= ((unsigned long long) *n
) / (unsigned) base
;
81 static int skip_atoi(const char **s
)
86 i
= i
*10 + *((*s
)++) - '0';
92 number(char * buf
, char * end
, long long num
, int base
, int size
, int precision
, int type
)
96 const char *small_digits
= "0123456789abcdefghijklmnopqrstuvwxyz";
97 const char *large_digits
= "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
100 digits
= (type
& LARGE
) ? large_digits
: small_digits
;
103 if (base
< 2 || base
> 36)
105 c
= (type
& ZEROPAD
) ? '0' : ' ';
112 } else if (type
& PLUS
) {
115 } else if (type
& SPACE
) {
121 if ((type
& SPECIAL
) && ((type
& REMOVEHEX
) == 0)) {
127 if ((num
== 0) && (precision
!=0))
129 else while (num
!= 0)
130 tmp
[i
++] = digits
[do_div(&num
,base
)];
134 if (!(type
&(ZEROPAD
+LEFT
))) {
147 if ((type
& SPECIAL
) && ((type
& REMOVEHEX
) == 0)) {
158 if (!(type
& LEFT
)) {
165 while (i
< precision
--) {
185 numberf(char * buf
, char * end
, double num
, int base
, int size
, int precision
, int type
)
189 const char *small_digits
= "0123456789abcdefghijklmnopqrstuvwxyz";
190 const char *large_digits
= "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
195 the float version of number is direcly copy of number
198 digits
= (type
& LARGE
) ? large_digits
: small_digits
;
201 if (base
< 2 || base
> 36)
203 c
= (type
& ZEROPAD
) ? '0' : ' ';
210 } else if (type
& PLUS
) {
213 } else if (type
& SPACE
) {
218 if (type
& SPECIAL
) {
227 else while (num
!= 0)
230 tmp
[i
++] = digits
[do_div(&x
,base
)];
231 #ifndef _M_ARM // Missing __floatdidf in CeGCC 0.55 -- GCC 4.4
238 if (!(type
&(ZEROPAD
+LEFT
))) {
250 if (type
& SPECIAL
) {
255 } else if (base
==16) {
264 if (!(type
& LEFT
)) {
271 while (i
< precision
--) {
290 string(char* buf
, char* end
, const char* s
, int len
, int field_width
, int precision
, int flags
)
295 c
= (flags
& ZEROPAD
) ? '0' : ' ';
307 while ((unsigned int)len
< (unsigned int)precision
&& s
[len
])
312 if ((unsigned int)len
> (unsigned int)precision
)
317 while (len
< field_width
--)
323 for (i
= 0; i
< len
; ++i
)
329 while (len
< field_width
--)
339 stringw(char* buf
, char* end
, const wchar_t* sw
, int len
, int field_width
, int precision
, int flags
)
344 c
= (flags
& ZEROPAD
) ? '0' : ' ';
356 while ((unsigned int)len
< (unsigned int)precision
&& sw
[len
])
361 if ((unsigned int)len
> (unsigned int)precision
)
366 while (len
< field_width
--)
372 for (i
= 0; i
< len
; ++i
)
375 *buf
= (unsigned char)(*sw
++);
378 while (len
< field_width
--)
390 int __cdecl
_vsnprintf(char *buf
, size_t cnt
, const char *fmt
, va_list args
)
393 unsigned long long num
;
401 int flags
; /* flags to number() */
403 int field_width
; /* width of output field */
404 int precision
; /* min. # of digits for integers; max
405 number of chars for from string */
406 int qualifier
; /* 'h', 'l', 'L', 'I' or 'w' for integer fields */
408 /* clear the string buffer with zero so we do not need NULL terment it at end */
417 for ( ; *fmt
; ++fmt
) {
428 ++fmt
; /* this also skips first '%' */
430 case '-': flags
|= LEFT
; goto repeat
;
431 case '+': flags
|= PLUS
; goto repeat
;
432 case ' ': flags
|= SPACE
; goto repeat
;
433 case '#': flags
|= SPECIAL
; goto repeat
;
434 case '0': flags
|= ZEROPAD
; goto repeat
;
437 /* get field width */
440 field_width
= skip_atoi(&fmt
);
441 else if (*fmt
== '*') {
443 /* it's the next argument */
444 field_width
= va_arg(args
, int);
445 if (field_width
< 0) {
446 field_width
= -field_width
;
451 /* get the precision */
456 precision
= skip_atoi(&fmt
);
457 else if (*fmt
== '*') {
459 /* it's the next argument */
460 precision
= va_arg(args
, int);
466 /* get the conversion qualifier */
468 if (*fmt
== 'l' && *(fmt
+1) == 'l') {
471 } else if (*fmt
== 'h' || *fmt
== 'l' || *fmt
== 'L' || *fmt
== 'w') {
474 } else if (*fmt
== 'I' && *(fmt
+1) == '6' && *(fmt
+2) == '4') {
477 } else if (*fmt
== 'I' && *(fmt
+1) == '3' && *(fmt
+2) == '2') {
480 } else if (*fmt
== 'F' && *(fmt
+1) == 'p') {
489 case 'c': /* finished */
490 if (qualifier
== 'l' || qualifier
== 'w') {
492 /* print unicode string */
493 sw1
[0] = (wchar_t) va_arg(args
, int);
495 str
= stringw(str
, end
, (wchar_t *)&sw1
, -1, field_width
, precision
, flags
);
498 /* print ascii string */
499 s1
[0] = ( unsigned char) va_arg(args
, int);
501 str
= string(str
, end
, (char *)&s1
, -1, field_width
, precision
, flags
);
505 case 'C': /* finished */
507 while (--field_width
> 0) {
512 if (qualifier
== 'h') {
514 *str
= (unsigned char) va_arg(args
, int);
518 *str
= (unsigned char)(wchar_t) va_arg(args
, int);
521 while (--field_width
> 0) {
528 case 's': /* finished */
529 if (qualifier
== 'l' || qualifier
== 'w') {
530 /* print unicode string */
531 sw
= va_arg(args
, wchar_t *);
532 str
= stringw(str
, end
, sw
, -1, field_width
, precision
, flags
);
534 /* print ascii string */
535 s
= va_arg(args
, char *);
536 str
= string(str
, end
, s
, -1, field_width
, precision
, flags
);
541 if (qualifier
== 'h') {
542 /* print ascii string */
543 s
= va_arg(args
, char *);
544 str
= string(str
, end
, s
, -1, field_width
, precision
, flags
);
546 /* print unicode string */
547 sw
= va_arg(args
, wchar_t *);
548 str
= stringw(str
, end
, sw
, -1, field_width
, precision
, flags
);
553 if (qualifier
== 'w') {
554 /* print counted unicode string */
555 PUNICODE_STRING pus
= va_arg(args
, PUNICODE_STRING
);
556 if ((pus
== NULL
) || (pus
->Buffer
== NULL
)) {
561 len
= pus
->Length
/ sizeof(WCHAR
);
563 str
= stringw(str
, end
, sw
, len
, field_width
, precision
, flags
);
565 /* print counted ascii string */
566 PANSI_STRING pus
= va_arg(args
, PANSI_STRING
);
567 if ((pus
== NULL
) || (pus
->Buffer
== NULL
)) {
574 str
= string(str
, end
, s
, len
, field_width
, precision
, flags
);
579 if ((flags
& LARGE
) == 0)
582 if (field_width
== -1) {
583 field_width
= 2 * sizeof(void *);
586 str
= number(str
, end
,
587 (ULONG_PTR
) va_arg(args
, void *), 16,
588 field_width
, precision
, flags
);
592 /* FIXME: What does C99 say about the overflow case here? */
593 if (qualifier
== 'l') {
594 long * ip
= va_arg(args
, long *);
597 int * ip
= va_arg(args
, int *);
602 /* float number formats - set up the flags and "break" */
608 _double
= (double)va_arg(args
, double);
609 if ( _isnan(_double
) ) {
618 } else if ( _isinf(_double
) < 0 ) {
627 } else if ( _isinf(_double
) > 0 ) {
637 if ( precision
== -1 )
639 str
= numberf(str
, end
, (int)_double
, base
, field_width
, precision
, flags
);
645 /* integer number formats - set up the flags and "break" */
676 if (qualifier
== 'I')
677 num
= va_arg(args
, unsigned long long);
678 else if (qualifier
== 'l') {
680 num
= va_arg(args
, long);
682 num
= va_arg(args
, unsigned long);
684 else if (qualifier
== 'h') {
686 num
= va_arg(args
, int);
688 num
= va_arg(args
, unsigned int);
692 num
= va_arg(args
, int);
694 num
= va_arg(args
, unsigned int);
696 str
= number(str
, end
, num
, base
, field_width
, precision
, flags
);
701 /* don't write out a null byte if the buf size is zero */
710 int sprintf(char * buf
, const char *fmt
, ...)
716 i
=_vsnprintf(buf
,MAXLONG
,fmt
,args
);
725 int _snprintf(char * buf
, size_t cnt
, const char *fmt
, ...)
731 i
=_vsnprintf(buf
,cnt
,fmt
,args
);
740 int __cdecl
vsprintf(char *buf
, const char *fmt
, va_list args
)
742 return _vsnprintf(buf
,MAXLONG
,fmt
,args
);