1 /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
4 #include <msvcrt/stdarg.h> // robd
5 #include <msvcrt/crttypes.h> // robd
7 #include <msvcrt/stdio.h>
8 #include <msvcrt/malloc.h>
9 #include <msvcrt/internal/file.h>
11 int _isnanl(double x);
12 int _isinfl(double x);
18 __vfwprintf(FILE *fp, const wchar_t *fmt0, va_list argp);
22 vfwprintf(FILE *f, const wchar_t *fmt, va_list ap)
25 wchar_t localbuf[BUFSIZ];
28 __fileno_lock(fileno(f));
30 if (f->_flag & _IONBF) {
32 f->_ptr = f->_base = (char *)localbuf;
34 len = __vfwprintf(f,fmt,ap);
41 len = __vfwprintf(f,fmt,ap);
43 __fileno_unlock(fileno(f));
45 return (ferror(f) ? EOF : len);
51 * linux/lib/vsprintf.c
53 * Copyright (C) 1991, 1992 Linus Torvalds
56 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
58 * Wirzenius wrote this portably, Torvalds fucked it up :-)
62 * Appropiated for the reactos kernel, March 1998 -- David Welch
65 #include <msvcrt/stdarg.h>
67 #include <msvcrt/ctype.h>
68 #include <msvcrt/string.h>
69 #include <msvcrt/stdio.h>
70 #include <msvcrt/string.h>
71 #include <msvcrt/math.h>
72 #include <msvcrt/internal/ieee.h>
75 #define ZEROPAD 1 /* pad with zero */
76 #define SIGN 2 /* unsigned/signed long */
77 #define PLUS 4 /* show plus */
78 #define SPACE 8 /* space if plus */
79 #define LEFT 16 /* left justified */
80 #define SPECIAL 32 /* 0x */
81 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
82 #define ZEROTRUNC 128 /* truncate zero 's */
85 static int skip_wtoi(const wchar_t **s)
90 i = i*10 + *((*s)++) - L'0';
95 static int do_div(LONGLONG *n,int base)
97 int __res = ((ULONGLONG) *n) % (unsigned) base;
98 *n = ((ULONGLONG) *n) / (unsigned) base;
103 static int number(FILE * f, LONGLONG num, int base, int size, int precision ,int type)
105 wchar_t c,sign,tmp[66];
106 const wchar_t *digits=L"0123456789abcdefghijklmnopqrstuvwxyz";
110 digits = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
113 if (base < 2 || base > 36)
115 c = (type & ZEROPAD) ? L'0' : L' ';
122 } else if (type & PLUS) {
125 } else if (type & SPACE) {
130 if (type & SPECIAL) {
139 else while (num != 0)
140 tmp[i++] = digits[do_div(&num,base)];
144 if (!(type&(ZEROPAD+LEFT)))
147 if (putwc(L' ',f) == WEOF)
154 if (putwc(sign,f) == WEOF)
158 if (type & SPECIAL) {
160 if (putwc(L'0',f) == WEOF)
165 if (putwc(L'0', f) == WEOF)
168 if (putwc(digits[33],f) == WEOF)
176 if (putwc(c,f) == WEOF)
180 while (i < precision--)
182 if (putwc(L'0', f) == WEOF)
188 if (putwc(tmp[i],f) == WEOF)
194 if (putwc(L' ', f) == WEOF)
202 static int numberf(FILE * f, double __n, wchar_t exp_sign, int size, int precision, int type)
204 double exponent = 0.0;
219 int result, done = 0;
221 double_t *n = (double_t *)&__n;
223 if ( exp_sign == L'g' || exp_sign == L'G' || exp_sign == L'e' || exp_sign == L'E' ) {
224 ie = ((unsigned int)n->exponent - (unsigned int)0x3ff);
225 exponent = ie/3.321928;
228 if ( exp_sign == L'g' || exp_sign == L'G' ) {
230 if ( exponent < -4 || fabs(exponent) >= precision )
231 exp_sign -= 2; // g -> e and G -> E
234 if ( exp_sign == L'e' || exp_sign == L'E' ) {
235 frac = modf(exponent,&e);
238 else if ( frac < -0.5 )
241 result = numberf(f,__n/pow(10.0L,e),L'f',size-4, precision, type);
245 if (putwc( exp_sign,f) == WEOF)
254 result = number(f,ie, 10,2, 2,type );
261 if ( exp_sign == 'f' ) {
267 c = (type & ZEROPAD) ? L'0' : L' ';
274 } else if (type & PLUS) {
277 } else if (type & SPACE) {
283 frac = modf(__n,&intr);
285 // # flags forces a . and prevents trucation of trailing zero's
287 if ( precision > 0 ) {
288 //frac = modfl(__n,&intr);
292 frac = modf(frac, &p);
293 buf[i] = (int)p + L'0';
304 if ( precision >= 1 || type & SPECIAL) {
315 while ( intr > 0.0 ) {
317 p = modf(intr, &intr);
321 buf[i++] = (int)p + L'0';
327 while ( j < i && ro == 1 ) {
328 if ( buf[j] >= L'0' && buf[j] <= L'8' ) {
332 else if ( buf[j] == L'9' ) {
343 if (!(type&(ZEROPAD+LEFT)))
346 if (putwc(L' ',f) == WEOF)
352 if (putwc( sign,f) == WEOF)
357 if (!(type&(ZEROPAD+LEFT)))
360 if (putwc(L' ',f) == WEOF)
364 if (type & SPECIAL) {
370 if (putwc(c,f) == WEOF)
376 if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) {
378 while ( j < i && ( *tmp == L'0' || *tmp == L'.' )) {
384 // while (i < precision--)
388 if (putwc(tmp[i],f) == WEOF)
394 if (putwc(L' ', f) == WEOF)
403 static int numberfl(FILE * f, long double __n, wchar_t exp_sign, int size, int precision, int type)
405 long double exponent = 0.0;
415 long double frac, intr;
421 int result, done = 0;
423 long_double_t *n = (long_double_t *)&__n;
425 if ( exp_sign == L'g' || exp_sign == L'G' || exp_sign == L'e' || exp_sign == L'E' ) {
426 ie = ((unsigned int)n->exponent - (unsigned int)0x3fff);
427 exponent = ie/3.321928;
430 if ( exp_sign == L'g' || exp_sign == L'G' ) {
432 if ( exponent < -4 || fabs(exponent) >= precision )
433 exp_sign -= 2; // g -> e and G -> E
436 if ( exp_sign == L'e' || exp_sign == L'E' ) {
437 frac = modfl(exponent,&e);
440 else if ( frac < -0.5 )
443 result = numberf(f,__n/powl(10.0L,e),L'f',size-4, precision, type);
447 if (putwc( exp_sign,f) == WEOF)
456 result = number(f,ie, 10,2, 2,type );
463 if ( exp_sign == L'f' ) {
469 c = (type & ZEROPAD) ? L'0' : L' ';
476 } else if (type & PLUS) {
479 } else if (type & SPACE) {
485 frac = modfl(__n,&intr);
487 // # flags forces a . and prevents trucation of trailing zero's
488 if ( precision > 0 ) {
489 //frac = modfl(__n,&intr);
494 frac = modfl((long double)frac, &p);
495 buf[i] = (int)p + L'0';
506 if ( precision >= 1 || type & SPECIAL) {
517 while ( intr > 0.0 ) {
519 p = modfl(intr, &intr);
523 buf[i++] = (int)p + L'0';
529 while ( j < i && ro == 1) {
530 if ( buf[j] >= L'0' && buf[j] <= L'8' ) {
534 else if ( buf[j] == L'9' ) {
545 if (!(type&(ZEROPAD+LEFT)))
551 if (!(type&(ZEROPAD+LEFT)))
554 if (type & SPECIAL) {
562 if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) {
564 while ( j < i && ( *tmp == L'0' || *tmp == L'.' )) {
570 // while (i < precision--)
574 if (putwc(tmp[i],f) == WEOF)
580 if (putwc(L' ', f) == WEOF)
588 static int string(FILE *f, const char* s, int len, int field_width, int precision, int flags)
601 while (s[len] && (unsigned int)len < (unsigned int)precision)
606 if ((unsigned int)len > (unsigned int)precision)
611 while (len < field_width--)
613 if (putwc(L' ', f) == WEOF)
617 for (i = 0; i < len; ++i)
619 if (putwc(*s++, f) == WEOF)
623 while (len < field_width--)
625 if (putwc(L' ', f) == WEOF)
632 static int stringw(FILE *f, const wchar_t* sw, int len, int field_width, int precision, int flags)
645 while (sw[len] && (unsigned int)len < (unsigned int)precision)
650 if ((unsigned int)len > (unsigned int)precision)
655 while (len < field_width--)
657 if (putwc(L' ', f) == WEOF)
661 for (i = 0; i < len; ++i)
663 if (putwc(*sw++, f) == WEOF)
667 while (len < field_width--)
669 if (putwc(L' ', f) == WEOF)
676 int __vfwprintf(FILE *f, const wchar_t *fmt, va_list args)
681 long double _ldouble;
685 int result, done = 0;
687 int flags; /* flags to number() */
689 int field_width; /* width of output field */
690 int precision; /* min. # of digits for integers; max
691 number of chars for from string */
692 int qualifier = 0; /* 'h', 'l', 'L' or 'I64' for integer fields */
694 for (; *fmt ; ++fmt) {
696 if (putwc(*fmt,f) == WEOF)
705 ++fmt; /* this also skips first '%' */
707 case L'-': flags |= LEFT; goto repeat;
708 case L'+': flags |= PLUS; goto repeat;
709 case L' ': flags |= SPACE; goto repeat;
710 case L'#': flags |= SPECIAL; goto repeat;
711 case L'0': flags |= ZEROPAD; goto repeat;
714 /* get field width */
717 field_width = skip_wtoi(&fmt);
718 else if (*fmt == L'*') {
720 /* it's the next argument */
721 field_width = va_arg(args, int);
722 if (field_width < 0) {
723 field_width = -field_width;
728 /* get the precision */
733 precision = skip_wtoi(&fmt);
734 else if (*fmt == L'*') {
736 /* it's the next argument */
737 precision = va_arg(args, int);
743 /* get the conversion qualifier */
745 // %Z can be just stand alone or as size_t qualifier
761 } else if (*fmt == L'h' || *fmt == L'l' || *fmt == L'L' || *fmt == L'w') {
764 } else if (*fmt == L'I' && *(fmt+1) == L'6' && *(fmt+2) == L'4') {
769 // go fine with ll instead of L
770 if ( *fmt == L'l' ) {
779 case L'c': /* finished */
781 while (--field_width > 0)
783 if (putwc(L' ', f) == WEOF)
787 if (qualifier == L'h')
789 if (putwc((wchar_t) va_arg(args, int), f) == WEOF)
794 if (putwc((wchar_t) va_arg(args, int), f) == WEOF)
798 while (--field_width > 0)
800 if (putwc(L' ', f) == WEOF)
806 case L'C': /* finished */
808 while (--field_width > 0)
810 if (putwc(L' ', f) == WEOF)
814 if (qualifier == L'l' || qualifier == L'w')
816 if (putwc((unsigned char) va_arg(args, int), f) == WEOF)
821 if (putwc((unsigned char) va_arg(args, int), f) == WEOF)
825 while (--field_width > 0)
827 if (putwc(L' ', f) == WEOF)
833 case L's': /* finished */
834 if (qualifier == L'h') {
835 /* print ascii string */
836 s = va_arg(args, char *);
837 result = string(f, s, -1, field_width, precision, flags);
839 /* print unicode string */
840 sw = va_arg(args, wchar_t *);
841 result = stringw(f, sw, -1, field_width, precision, flags);
849 if (qualifier == L'l' || qualifier == L'w') {
850 /* print unicode string */
851 sw = va_arg(args, wchar_t *);
852 result = stringw(f, sw, -1, field_width, precision, flags);
854 /* print ascii string */
855 s = va_arg(args, char *);
862 case L'Z': /* finished */
863 if (qualifier == L'w') {
864 /* print counted unicode string */
865 PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING);
866 if ((pus == NULL) || (pus->Buffer)) {
872 result = stringw(f, sw, len, field_width, precision, flags);
874 /* print counted ascii string */
875 PANSI_STRING pus = va_arg(args, PANSI_STRING);
876 if ((pus == NULL) || (pus->Buffer)) {
883 result = string(f, s, len, field_width, precision, flags);
890 case L'e': /* finished */
895 if (qualifier == L'l' || qualifier == L'L' ) {
896 _ldouble = va_arg(args, long double);
898 if ( _isnanl(_ldouble) ) {
902 if (putwc(*sw++,f) == WEOF)
908 else if ( _isinfl(_ldouble) < 0 ) {
912 if (putwc(*sw++,f) == WEOF)
918 else if ( _isinfl(_ldouble) > 0 ) {
922 if (putwc(*sw++,f) == WEOF)
928 if ( precision == -1 )
930 result = numberfl(f,_ldouble,*fmt,field_width,precision,flags);
936 _double = (double)va_arg(args, double);
938 if ( _isnan(_double) ) {
942 if (putwc(*sw++,f) == WEOF)
947 } else if ( _isinf(_double) < 0 ) {
951 if (putwc(*sw++,f) == WEOF)
956 } else if ( _isinf(_double) > 0 ) {
960 if (putwc(*sw++,f) == WEOF)
966 if ( precision == -1 )
968 result = numberf(f,_double,*fmt,field_width,precision,flags);
977 if (field_width == -1) {
978 field_width = 2*sizeof(void *);
982 (unsigned long) va_arg(args, void *), 16,
983 field_width, precision, flags);
990 if (qualifier == L'l') {
991 long * ip = va_arg(args, long *);
994 int * ip = va_arg(args, int *);
999 /* integer number formats - set up the flags and "break" */
1023 if (putwc(L'%', f) == WEOF)
1029 if (putwc(*fmt, f) == WEOF)
1038 if (qualifier == L'I')
1039 num = va_arg(args, ULONGLONG);
1040 else if (qualifier == L'l')
1041 num = va_arg(args, unsigned long);
1042 else if (qualifier == L'h') {
1044 num = va_arg(args, int);
1046 num = va_arg(args, unsigned int);
1048 else if (flags & SIGN)
1049 num = va_arg(args, int);
1051 num = va_arg(args, unsigned int);
1052 result = number(f, num, base, field_width, precision, flags);