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);
25 vfwprintf(FILE *f, const wchar_t *fmt, va_list ap)
28 wchar_t localbuf[BUFSIZ];
31 __fileno_lock(fileno(f));
33 if (f->_flag & _IONBF) {
35 f->_ptr = f->_base = (char *)localbuf;
37 len = __vfwprintf(f,fmt,ap);
44 len = __vfwprintf(f,fmt,ap);
46 __fileno_unlock(fileno(f));
48 return (ferror(f) ? EOF : len);
54 * linux/lib/vsprintf.c
56 * Copyright (C) 1991, 1992 Linus Torvalds
59 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
61 * Wirzenius wrote this portably, Torvalds fucked it up :-)
65 * Appropiated for the reactos kernel, March 1998 -- David Welch
68 #include <msvcrt/stdarg.h>
70 #include <msvcrt/ctype.h>
71 #include <msvcrt/string.h>
72 #include <msvcrt/stdio.h>
73 #include <msvcrt/string.h>
74 #include <msvcrt/math.h>
75 #include <msvcrt/internal/ieee.h>
78 #define ZEROPAD 1 /* pad with zero */
79 #define SIGN 2 /* unsigned/signed long */
80 #define PLUS 4 /* show plus */
81 #define SPACE 8 /* space if plus */
82 #define LEFT 16 /* left justified */
83 #define SPECIAL 32 /* 0x */
84 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
85 #define ZEROTRUNC 128 /* truncate zero 's */
88 static int skip_wtoi(const wchar_t **s)
93 i = i*10 + *((*s)++) - L'0';
98 static int do_div(LONGLONG *n,int base)
100 int __res = ((ULONGLONG) *n) % (unsigned) base;
101 *n = ((ULONGLONG) *n) / (unsigned) base;
106 static int number(FILE * f, LONGLONG num, int base, int size, int precision ,int type)
108 wchar_t c,sign,tmp[66];
109 const wchar_t *digits=L"0123456789abcdefghijklmnopqrstuvwxyz";
113 digits = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
116 if (base < 2 || base > 36)
118 c = (type & ZEROPAD) ? L'0' : L' ';
125 } else if (type & PLUS) {
128 } else if (type & SPACE) {
133 if (type & SPECIAL) {
142 else while (num != 0)
143 tmp[i++] = digits[do_div(&num,base)];
147 if (!(type&(ZEROPAD+LEFT)))
150 if (putwc(L' ',f) == WEOF)
157 if (putwc(sign,f) == WEOF)
161 if (type & SPECIAL) {
163 if (putwc(L'0',f) == WEOF)
168 if (putwc(L'0', f) == WEOF)
171 if (putwc(digits[33],f) == WEOF)
179 if (putwc(c,f) == WEOF)
183 while (i < precision--)
185 if (putwc(L'0', f) == WEOF)
191 if (putwc(tmp[i],f) == WEOF)
197 if (putwc(L' ', f) == WEOF)
205 static int numberf(FILE * f, double __n, wchar_t exp_sign, int size, int precision, int type)
207 double exponent = 0.0;
222 int result, done = 0;
224 double_t *n = (double_t *)&__n;
226 if ( exp_sign == L'g' || exp_sign == L'G' || exp_sign == L'e' || exp_sign == L'E' ) {
227 ie = ((unsigned int)n->exponent - (unsigned int)0x3ff);
228 exponent = ie/3.321928;
231 if ( exp_sign == L'g' || exp_sign == L'G' ) {
233 if ( exponent < -4 || fabs(exponent) >= precision )
234 exp_sign -= 2; // g -> e and G -> E
237 if ( exp_sign == L'e' || exp_sign == L'E' ) {
238 frac = modf(exponent,&e);
241 else if ( frac < -0.5 )
244 result = numberf(f,__n/pow(10.0L,e),L'f',size-4, precision, type);
248 if (putwc( exp_sign,f) == WEOF)
257 result = number(f,ie, 10,2, 2,type );
264 if ( exp_sign == 'f' ) {
270 c = (type & ZEROPAD) ? L'0' : L' ';
277 } else if (type & PLUS) {
280 } else if (type & SPACE) {
286 frac = modf(__n,&intr);
288 // # flags forces a . and prevents trucation of trailing zero's
290 if ( precision > 0 ) {
291 //frac = modfl(__n,&intr);
295 frac = modf(frac, &p);
296 buf[i] = (int)p + L'0';
307 if ( precision >= 1 || type & SPECIAL) {
318 while ( intr > 0.0 ) {
325 buf[i++] = (int)p + L'0';
331 while ( j < i && ro == 1 ) {
332 if ( buf[j] >= L'0' && buf[j] <= L'8' ) {
336 else if ( buf[j] == L'9' ) {
347 if (!(type&(ZEROPAD+LEFT)))
350 if (putwc(L' ',f) == WEOF)
356 if (putwc( sign,f) == WEOF)
361 if (!(type&(ZEROPAD+LEFT)))
364 if (putwc(L' ',f) == WEOF)
368 if (type & SPECIAL) {
374 if (putwc(c,f) == WEOF)
380 if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) {
382 while ( j < i && ( *tmp == L'0' || *tmp == L'.' )) {
388 // while (i < precision--)
392 if (putwc(tmp[i],f) == WEOF)
398 if (putwc(L' ', f) == WEOF)
407 static int numberfl(FILE * f, long double __n, wchar_t exp_sign, int size, int precision, int type)
409 long double exponent = 0.0;
419 long double frac, intr;
425 int result, done = 0;
427 long_double_t *n = (long_double_t *)&__n;
429 if ( exp_sign == L'g' || exp_sign == L'G' || exp_sign == L'e' || exp_sign == L'E' ) {
430 ie = ((unsigned int)n->exponent - (unsigned int)0x3fff);
431 exponent = ie/3.321928;
434 if ( exp_sign == L'g' || exp_sign == L'G' ) {
436 if ( exponent < -4 || fabs(exponent) >= precision )
437 exp_sign -= 2; // g -> e and G -> E
440 if ( exp_sign == L'e' || exp_sign == L'E' ) {
441 frac = modfl(exponent,&e);
444 else if ( frac < -0.5 )
447 result = numberf(f,__n/powl(10.0L,e),L'f',size-4, precision, type);
451 if (putwc( exp_sign,f) == WEOF)
460 result = number(f,ie, 10,2, 2,type );
467 if ( exp_sign == L'f' ) {
473 c = (type & ZEROPAD) ? L'0' : L' ';
480 } else if (type & PLUS) {
483 } else if (type & SPACE) {
489 frac = modfl(__n,&intr);
491 // # flags forces a . and prevents trucation of trailing zero's
492 if ( precision > 0 ) {
493 //frac = modfl(__n,&intr);
498 frac = modfl((long double)frac, &p);
499 buf[i] = (int)p + L'0';
510 if ( precision >= 1 || type & SPECIAL) {
521 while ( intr > 0.0 ) {
528 buf[i++] = (int)p + L'0';
534 while ( j < i && ro == 1) {
535 if ( buf[j] >= L'0' && buf[j] <= L'8' ) {
539 else if ( buf[j] == L'9' ) {
550 if (!(type&(ZEROPAD+LEFT)))
556 if (!(type&(ZEROPAD+LEFT)))
559 if (type & SPECIAL) {
567 if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) {
569 while ( j < i && ( *tmp == L'0' || *tmp == L'.' )) {
575 // while (i < precision--)
579 if (putwc(tmp[i],f) == WEOF)
585 if (putwc(L' ', f) == WEOF)
593 static int string(FILE *f, const char* s, int len, int field_width, int precision, int flags)
606 while (s[len] && (unsigned int)len < (unsigned int)precision)
611 if ((unsigned int)len > (unsigned int)precision)
616 while (len < field_width--)
618 if (putwc(L' ', f) == WEOF)
622 for (i = 0; i < len; ++i)
624 if (putwc(*s++, f) == WEOF)
628 while (len < field_width--)
630 if (putwc(L' ', f) == WEOF)
637 static int stringw(FILE *f, const wchar_t* sw, int len, int field_width, int precision, int flags)
650 while (sw[len] && (unsigned int)len < (unsigned int)precision)
655 if ((unsigned int)len > (unsigned int)precision)
660 while (len < field_width--)
662 if (putwc(L' ', f) == WEOF)
666 for (i = 0; i < len; ++i)
668 if (putwc(*sw++, f) == WEOF)
672 while (len < field_width--)
674 if (putwc(L' ', f) == WEOF)
681 int __vfwprintf(FILE *f, const wchar_t *fmt, va_list args)
686 long double _ldouble;
690 int result, done = 0;
692 int flags; /* flags to number() */
694 int field_width; /* width of output field */
695 int precision; /* min. # of digits for integers; max
696 number of chars for from string */
697 int qualifier = 0; /* 'h', 'l', 'L' or 'I64' for integer fields */
699 for (; *fmt ; ++fmt) {
701 if (putwc(*fmt,f) == WEOF)
710 ++fmt; /* this also skips first '%' */
712 case L'-': flags |= LEFT; goto repeat;
713 case L'+': flags |= PLUS; goto repeat;
714 case L' ': flags |= SPACE; goto repeat;
715 case L'#': flags |= SPECIAL; goto repeat;
716 case L'0': flags |= ZEROPAD; goto repeat;
719 /* get field width */
722 field_width = skip_wtoi(&fmt);
723 else if (*fmt == L'*') {
725 /* it's the next argument */
726 field_width = va_arg(args, int);
727 if (field_width < 0) {
728 field_width = -field_width;
733 /* get the precision */
738 precision = skip_wtoi(&fmt);
739 else if (*fmt == L'*') {
741 /* it's the next argument */
742 precision = va_arg(args, int);
748 /* get the conversion qualifier */
750 // %Z can be just stand alone or as size_t qualifier
766 } else if (*fmt == L'h' || *fmt == L'l' || *fmt == L'L' || *fmt == L'w') {
769 } else if (*fmt == L'I' && *(fmt+1) == L'6' && *(fmt+2) == L'4') {
774 // go fine with ll instead of L
775 if ( *fmt == L'l' ) {
784 case L'c': /* finished */
786 while (--field_width > 0)
788 if (putwc(L' ', f) == WEOF)
792 if (qualifier == L'h')
794 if (putwc((wchar_t) va_arg(args, int), f) == WEOF)
799 if (putwc((wchar_t) va_arg(args, int), f) == WEOF)
803 while (--field_width > 0)
805 if (putwc(L' ', f) == WEOF)
811 case L'C': /* finished */
813 while (--field_width > 0)
815 if (putwc(L' ', f) == WEOF)
819 if (qualifier == L'l' || qualifier == L'w')
821 if (putwc((unsigned char) va_arg(args, int), f) == WEOF)
826 if (putwc((unsigned char) va_arg(args, int), f) == WEOF)
830 while (--field_width > 0)
832 if (putwc(L' ', f) == WEOF)
838 case L's': /* finished */
839 if (qualifier == L'h') {
840 /* print ascii string */
841 s = va_arg(args, char *);
842 result = string(f, s, -1, field_width, precision, flags);
844 /* print unicode string */
845 sw = va_arg(args, wchar_t *);
846 result = stringw(f, sw, -1, field_width, precision, flags);
854 if (qualifier == L'l' || qualifier == L'w') {
855 /* print unicode string */
856 sw = va_arg(args, wchar_t *);
857 result = stringw(f, sw, -1, field_width, precision, flags);
859 /* print ascii string */
860 s = va_arg(args, char *);
861 result = string(f, s, -1, field_width, precision, flags);
868 case L'Z': /* finished */
869 if (qualifier == L'w') {
870 /* print counted unicode string */
871 PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING);
872 if ((pus == NULL) || (pus->Buffer)) {
878 result = stringw(f, sw, len, field_width, precision, flags);
880 /* print counted ascii string */
881 PANSI_STRING pus = va_arg(args, PANSI_STRING);
882 if ((pus == NULL) || (pus->Buffer)) {
889 result = string(f, s, len, field_width, precision, flags);
896 case L'e': /* finished */
901 if (qualifier == L'l' || qualifier == L'L' ) {
902 _ldouble = va_arg(args, long double);
904 if ( _isnanl(_ldouble) ) {
908 if (putwc(*sw++,f) == WEOF)
914 else if ( _isinfl(_ldouble) < 0 ) {
918 if (putwc(*sw++,f) == WEOF)
924 else if ( _isinfl(_ldouble) > 0 ) {
928 if (putwc(*sw++,f) == WEOF)
934 if ( precision == -1 )
936 result = numberfl(f,_ldouble,*fmt,field_width,precision,flags);
942 _double = (double)va_arg(args, double);
944 if ( _isnan(_double) ) {
948 if (putwc(*sw++,f) == WEOF)
953 } else if ( _isinf(_double) < 0 ) {
957 if (putwc(*sw++,f) == WEOF)
962 } else if ( _isinf(_double) > 0 ) {
966 if (putwc(*sw++,f) == WEOF)
972 if ( precision == -1 )
974 result = numberf(f,_double,*fmt,field_width,precision,flags);
983 if (field_width == -1) {
984 field_width = 2*sizeof(void *);
988 (unsigned long) va_arg(args, void *), 16,
989 field_width, precision, flags);
996 if (qualifier == L'l') {
997 long * ip = va_arg(args, long *);
1000 int * ip = va_arg(args, int *);
1005 /* integer number formats - set up the flags and "break" */
1029 if (putwc(L'%', f) == WEOF)
1035 if (putwc(*fmt, f) == WEOF)
1044 if (qualifier == L'I')
1045 num = va_arg(args, ULONGLONG);
1046 else if (qualifier == L'l')
1047 num = va_arg(args, unsigned long);
1048 else if (qualifier == L'h') {
1050 num = va_arg(args, int);
1052 num = va_arg(args, unsigned int);
1054 else if (flags & SIGN)
1055 num = va_arg(args, int);
1057 num = va_arg(args, unsigned int);
1058 result = number(f, num, base, field_width, precision, flags);