build msvcrt and crtdll from same source via lib\crt
[reactos.git] / reactos / lib / crt / stdio / vfwprint.c
1 /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
2
3 #ifdef __USE_W32API
4 #undef __USE_W32API
5 #endif
6
7 //#include <stdarg.h>
8 #include <msvcrt/stdarg.h> // robd
9 #include <msvcrt/crttypes.h> // robd
10
11 #include <msvcrt/stdio.h>
12 #include <msvcrt/malloc.h>
13 #include <msvcrt/internal/file.h>
14
15
16 int _isnanl(double x);
17 int _isinfl(double x);
18 int _isnan(double x);
19 int _isinf(double x);
20
21
22 int
23 __vfwprintf(FILE *fp, const wchar_t *fmt0, va_list argp);
24
25
26 /*
27 * @implemented
28 */
29 int
30 vfwprintf(FILE *f, const wchar_t *fmt, va_list ap)
31 {
32 int len;
33 wchar_t localbuf[BUFSIZ];
34
35 #if 0
36 __fileno_lock(fileno(f));
37 #endif
38 if (f->_flag & _IONBF) {
39 f->_flag &= ~_IONBF;
40 f->_ptr = f->_base = (char *)localbuf;
41 f->_bufsiz = BUFSIZ;
42 len = __vfwprintf(f,fmt,ap);
43 (void)fflush(f);
44 f->_flag |= _IONBF;
45 f->_base = NULL;
46 f->_bufsiz = 0;
47 f->_cnt = 0;
48 } else
49 len = __vfwprintf(f,fmt,ap);
50 #if 0
51 __fileno_unlock(fileno(f));
52 #endif
53 return (ferror(f) ? EOF : len);
54 }
55
56
57
58 /*
59 * linux/lib/vsprintf.c
60 *
61 * Copyright (C) 1991, 1992 Linus Torvalds
62 */
63
64 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
65 /*
66 * Wirzenius wrote this portably, Torvalds fucked it up :-)
67 */
68
69 /*
70 * Appropiated for the reactos kernel, March 1998 -- David Welch
71 */
72
73 #include <msvcrt/stdarg.h>
74
75 #include <msvcrt/ctype.h>
76 #include <msvcrt/string.h>
77 #include <msvcrt/stdio.h>
78 #include <msvcrt/string.h>
79 #include <msvcrt/math.h>
80 #include <msvcrt/internal/ieee.h>
81
82
83 #define ZEROPAD 1 /* pad with zero */
84 #define SIGN 2 /* unsigned/signed long */
85 #define PLUS 4 /* show plus */
86 #define SPACE 8 /* space if plus */
87 #define LEFT 16 /* left justified */
88 #define SPECIAL 32 /* 0x */
89 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
90 #define ZEROTRUNC 128 /* truncate zero 's */
91
92
93 static int skip_wtoi(const wchar_t **s)
94 {
95 int i=0;
96
97 while (iswdigit(**s))
98 i = i*10 + *((*s)++) - L'0';
99 return i;
100 }
101
102
103 static int do_div(LONGLONG *n,int base)
104 {
105 int __res = ((ULONGLONG) *n) % (unsigned) base;
106 *n = ((ULONGLONG) *n) / (unsigned) base;
107 return __res;
108 }
109
110
111 static int number(FILE * f, LONGLONG num, int base, int size, int precision ,int type)
112 {
113 wchar_t c,sign,tmp[66];
114 const wchar_t *digits=L"0123456789abcdefghijklmnopqrstuvwxyz";
115 int i, done = 0;
116
117 if (type & LARGE)
118 digits = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
119 if (type & LEFT)
120 type &= ~ZEROPAD;
121 if (base < 2 || base > 36)
122 return done;
123 c = (type & ZEROPAD) ? L'0' : L' ';
124 sign = 0;
125 if (type & SIGN) {
126 if (num < 0) {
127 sign = L'-';
128 num = -num;
129 size--;
130 } else if (type & PLUS) {
131 sign = L'+';
132 size--;
133 } else if (type & SPACE) {
134 sign = L' ';
135 size--;
136 }
137 }
138 if (type & SPECIAL) {
139 if (base == 16)
140 size -= 2;
141 else if (base == 8)
142 size--;
143 }
144 i = 0;
145 if (num == 0)
146 tmp[i++]=L'0';
147 else while (num != 0)
148 tmp[i++] = digits[do_div(&num,base)];
149 if (i > precision)
150 precision = i;
151 size -= precision;
152 if (!(type&(ZEROPAD+LEFT)))
153 while(size-->0)
154 {
155 if (putwc(L' ',f) == WEOF)
156 return -1;
157 done++;
158 }
159
160 if (sign)
161 {
162 if (putwc(sign,f) == WEOF)
163 return -1;
164 done++;
165 }
166 if (type & SPECIAL) {
167 if (base==8) {
168 if (putwc(L'0',f) == WEOF)
169 return -1;
170 done++;
171 }
172 else if (base==16) {
173 if (putwc(L'0', f) == WEOF)
174 return -1;
175 done++;
176 if (putwc(digits[33],f) == WEOF)
177 return -1;
178 done++;
179 }
180 }
181 if (!(type & LEFT))
182 while (size-- > 0)
183 {
184 if (putwc(c,f) == WEOF)
185 return -1;
186 done++;
187 }
188 while (i < precision--)
189 {
190 if (putwc(L'0', f) == WEOF)
191 return -1;
192 done++;
193 }
194 while (i-- > 0)
195 {
196 if (putwc(tmp[i],f) == WEOF)
197 return -1;
198 done++;
199 }
200 while (size-- > 0)
201 {
202 if (putwc(L' ', f) == WEOF)
203 return -1;
204 done++;
205 }
206 return done;
207 }
208
209
210 static int numberf(FILE * f, double __n, wchar_t exp_sign, int size, int precision, int type)
211 {
212 double exponent = 0.0;
213 double e;
214 long ie;
215
216 //int x;
217 char *buf, *tmp;
218 int i = 0;
219 int j = 0;
220 //int k = 0;
221
222 double frac, intr;
223 double p;
224 wchar_t sign;
225 wchar_t c;
226 char ro = 0;
227 int result, done = 0;
228
229 union
230 {
231 double* __n;
232 double_t* n;
233 } n;
234
235 n.__n = &__n;
236
237 if ( exp_sign == L'g' || exp_sign == L'G' || exp_sign == L'e' || exp_sign == L'E' ) {
238 ie = ((unsigned int)n.n->exponent - (unsigned int)0x3ff);
239 exponent = ie/3.321928;
240 }
241
242 if ( exp_sign == L'g' || exp_sign == L'G' ) {
243 type |= ZEROTRUNC;
244 if ( exponent < -4 || fabs(exponent) >= precision )
245 exp_sign -= 2; // g -> e and G -> E
246 }
247
248 if ( exp_sign == L'e' || exp_sign == L'E' ) {
249 frac = modf(exponent,&e);
250 if ( frac > 0.5 )
251 e++;
252 else if ( frac < -0.5 )
253 e--;
254
255 result = numberf(f,__n/pow(10.0L,e),L'f',size-4, precision, type);
256 if (result < 0)
257 return -1;
258 done += result;
259 if (putwc( exp_sign,f) == WEOF)
260 return -1;
261 done++;
262 size--;
263 ie = (long)e;
264 type = LEFT | PLUS;
265 if ( ie < 0 )
266 type |= SIGN;
267
268 result = number(f,ie, 10,2, 2,type );
269 if (result < 0)
270 return -1;
271 done += result;
272 return done;
273 }
274
275 if ( exp_sign == 'f' ) {
276 buf = alloca(4096);
277 if (type & LEFT) {
278 type &= ~ZEROPAD;
279 }
280
281 c = (type & ZEROPAD) ? L'0' : L' ';
282 sign = 0;
283 if (type & SIGN) {
284 if (__n < 0) {
285 sign = L'-';
286 __n = fabs(__n);
287 size--;
288 } else if (type & PLUS) {
289 sign = L'+';
290 size--;
291 } else if (type & SPACE) {
292 sign = L' ';
293 size--;
294 }
295 }
296
297 frac = modf(__n,&intr);
298
299 // # flags forces a . and prevents trucation of trailing zero's
300
301 if ( precision > 0 ) {
302 //frac = modfl(__n,&intr);
303 i = precision-1;
304 while ( i >= 0 ) {
305 frac*=10.0L;
306 frac = modf(frac, &p);
307 buf[i] = (int)p + L'0';
308 i--;
309 }
310 i = precision;
311 size -= precision;
312
313 ro = 0;
314 if ( frac > 0.5 ) {
315 ro = 1;
316 }
317
318 if ( precision >= 1 || type & SPECIAL) {
319 buf[i++] = '.';
320 size--;
321 }
322 }
323
324 if ( intr == 0.0 ) {
325 buf[i++] = L'0';
326 size--;
327 }
328 else {
329 while ( intr > 0.0 ) {
330 p = intr;
331 intr/=10.0L;
332 modf(intr, &intr);
333
334 p -= 10.0*intr;
335
336 buf[i++] = (int)p + L'0';
337 size--;
338 }
339 }
340
341 j = 0;
342 while ( j < i && ro == 1 ) {
343 if ( buf[j] >= L'0' && buf[j] <= L'8' ) {
344 buf[j]++;
345 ro = 0;
346 }
347 else if ( buf[j] == L'9' ) {
348 buf[j] = L'0';
349 }
350 j++;
351 }
352 if ( ro == 1 )
353 buf[i++] = L'1';
354
355 buf[i] = 0;
356
357 size -= precision;
358 if (!(type&(ZEROPAD+LEFT)))
359 while(size-->0)
360 {
361 if (putwc(L' ',f) == WEOF)
362 return -1;
363 done++;
364 }
365 if (sign)
366 {
367 if (putwc( sign,f) == WEOF)
368 return -1;
369 done++;
370 }
371
372 if (!(type&(ZEROPAD+LEFT)))
373 while(size-->0)
374 {
375 if (putwc(L' ',f) == WEOF)
376 return -1;
377 done++;
378 }
379 if (type & SPECIAL) {
380 }
381
382 if (!(type & LEFT))
383 while (size-- > 0)
384 {
385 if (putwc(c,f) == WEOF)
386 return -1;
387 done++;
388 }
389
390 tmp = buf;
391 if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) {
392 j = 0;
393 while ( j < i && ( *tmp == L'0' || *tmp == L'.' )) {
394 tmp++;
395 i--;
396 }
397 }
398 // else
399 // while (i < precision--)
400 // putwc(L'0', f);
401 while (i-- > 0)
402 {
403 if (putwc(tmp[i],f) == WEOF)
404 return -1;
405 done++;
406 }
407 while (size-- > 0)
408 {
409 if (putwc(L' ', f) == WEOF)
410 return -1;
411 done++;
412 }
413 }
414 return done;
415 }
416
417
418
419 static int string(FILE *f, const char* s, int len, int field_width, int precision, int flags)
420 {
421 int i, done = 0;
422 if (s == NULL)
423 {
424 s = "<NULL>";
425 len = 6;
426 }
427 else
428 {
429 if (len == -1)
430 {
431 len = 0;
432 while ((unsigned int)len < (unsigned int)precision && s[len])
433 len++;
434 }
435 else
436 {
437 if ((unsigned int)len > (unsigned int)precision)
438 len = precision;
439 }
440 }
441 if (!(flags & LEFT))
442 while (len < field_width--)
443 {
444 if (putwc(L' ', f) == WEOF)
445 return -1;
446 done++;
447 }
448 for (i = 0; i < len; ++i)
449 {
450 if (putwc(*s++, f) == WEOF)
451 return -1;
452 done++;
453 }
454 while (len < field_width--)
455 {
456 if (putwc(L' ', f) == WEOF)
457 return -1;
458 done++;
459 }
460 return done;
461 }
462
463 static int stringw(FILE *f, const wchar_t* sw, int len, int field_width, int precision, int flags)
464 {
465 int i, done = 0;
466 if (sw == NULL)
467 {
468 sw = L"<NULL>";
469 len = 6;
470 }
471 else
472 {
473 if (len == -1)
474 {
475 len = 0;
476 while ((unsigned int)len < (unsigned int)precision && sw[len])
477 len++;
478 }
479 else
480 {
481 if ((unsigned int)len > (unsigned int)precision)
482 len = precision;
483 }
484 }
485 if (!(flags & LEFT))
486 while (len < field_width--)
487 {
488 if (putwc(L' ', f) == WEOF)
489 return -1;
490 done++;
491 }
492 for (i = 0; i < len; ++i)
493 {
494 if (putwc(*sw++, f) == WEOF)
495 return -1;
496 done++;
497 }
498 while (len < field_width--)
499 {
500 if (putwc(L' ', f) == WEOF)
501 return -1;
502 done++;
503 }
504 return done;
505 }
506
507 int __vfwprintf(FILE *f, const wchar_t *fmt, va_list args)
508 {
509 int len = 0;
510 ULONGLONG num;
511 int base;
512 double _double;
513 const char *s;
514 const wchar_t* sw;
515 int result, done = 0;
516
517 int flags; /* flags to number() */
518
519 int field_width; /* width of output field */
520 int precision; /* min. # of digits for integers; max
521 number of chars for from string */
522 int qualifier = 0; /* 'h', 'l', 'L' or 'I64' for integer fields */
523
524 for (; *fmt ; ++fmt) {
525 if (*fmt != L'%') {
526 if (putwc(*fmt,f) == WEOF)
527 return -1;
528 done++;
529 continue;
530 }
531
532 /* process flags */
533 flags = 0;
534 repeat:
535 ++fmt; /* this also skips first '%' */
536 switch (*fmt) {
537 case L'-': flags |= LEFT; goto repeat;
538 case L'+': flags |= PLUS; goto repeat;
539 case L' ': flags |= SPACE; goto repeat;
540 case L'#': flags |= SPECIAL; goto repeat;
541 case L'0': flags |= ZEROPAD; goto repeat;
542 }
543
544 /* get field width */
545 field_width = -1;
546 if (isxdigit(*fmt))
547 field_width = skip_wtoi(&fmt);
548 else if (*fmt == L'*') {
549 ++fmt;
550 /* it's the next argument */
551 field_width = va_arg(args, int);
552 if (field_width < 0) {
553 field_width = -field_width;
554 flags |= LEFT;
555 }
556 }
557
558 /* get the precision */
559 precision = -1;
560 if (*fmt == L'.') {
561 ++fmt;
562 if (iswdigit(*fmt))
563 precision = skip_wtoi(&fmt);
564 else if (*fmt == L'*') {
565 ++fmt;
566 /* it's the next argument */
567 precision = va_arg(args, int);
568 }
569 if (precision < 0)
570 precision = 0;
571 }
572
573 /* get the conversion qualifier */
574 qualifier=0;
575 // %Z can be just stand alone or as size_t qualifier
576 if ( *fmt == 'Z' ) {
577 qualifier = *fmt;
578 switch ( *(fmt+1)) {
579 case L'o':
580 case L'b':
581 case L'X':
582 case L'x':
583 case L'd':
584 case L'i':
585 case L'u':
586 ++fmt;
587 break;
588 default:
589 break;
590 }
591 } else if (*fmt == L'h' || *fmt == L'l' || *fmt == L'L' || *fmt == L'w') {
592 qualifier = *fmt;
593 ++fmt;
594 } else if (*fmt == L'I' && *(fmt+1) == L'6' && *(fmt+2) == L'4') {
595 qualifier = *fmt;
596 fmt += 3;
597 }
598
599 // go fine with ll instead of L
600 if ( *fmt == L'l' ) {
601 ++fmt;
602 qualifier = L'L';
603 }
604
605 /* default base */
606 base = 10;
607
608 switch (*fmt) {
609 case L'c': /* finished */
610 if (!(flags & LEFT))
611 while (--field_width > 0)
612 {
613 if (putwc(L' ', f) == WEOF)
614 return -1;
615 done++;
616 }
617 if (qualifier == L'h')
618 {
619 if (putwc((wchar_t) va_arg(args, int), f) == WEOF)
620 return -1;
621 }
622 else
623 {
624 if (putwc((wchar_t) va_arg(args, int), f) == WEOF)
625 return -1;
626 }
627 done++;
628 while (--field_width > 0)
629 {
630 if (putwc(L' ', f) == WEOF)
631 return -1;
632 done++;
633 }
634 continue;
635
636 case L'C': /* finished */
637 if (!(flags & LEFT))
638 while (--field_width > 0)
639 {
640 if (putwc(L' ', f) == WEOF)
641 return -1;
642 done++;
643 }
644 if (qualifier == L'l' || qualifier == L'w')
645 {
646 if (putwc((unsigned char) va_arg(args, int), f) == WEOF)
647 return -1;
648 }
649 else
650 {
651 if (putwc((unsigned char) va_arg(args, int), f) == WEOF)
652 return -1;
653 }
654 done++;
655 while (--field_width > 0)
656 {
657 if (putwc(L' ', f) == WEOF)
658 return -1;
659 done++;
660 }
661 continue;
662
663 case L's': /* finished */
664 if (qualifier == L'h') {
665 /* print ascii string */
666 s = va_arg(args, char *);
667 result = string(f, s, -1, field_width, precision, flags);
668 } else {
669 /* print unicode string */
670 sw = va_arg(args, wchar_t *);
671 result = stringw(f, sw, -1, field_width, precision, flags);
672 }
673 if (result < 0)
674 return -1;
675 done += result;
676 continue;
677
678 case L'S':
679 if (qualifier == L'l' || qualifier == L'w') {
680 /* print unicode string */
681 sw = va_arg(args, wchar_t *);
682 result = stringw(f, sw, -1, field_width, precision, flags);
683 } else {
684 /* print ascii string */
685 s = va_arg(args, char *);
686 result = string(f, s, -1, field_width, precision, flags);
687 }
688 if (result < 0)
689 return -1;
690 done += result;
691 continue;
692
693 case L'Z': /* finished */
694 if (qualifier == L'w') {
695 /* print counted unicode string */
696 PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING);
697 if ((pus == NULL) || (pus->Buffer)) {
698 sw = NULL;
699 len = -1;
700 } else {
701 sw = pus->Buffer;
702 }
703 result = stringw(f, sw, len, field_width, precision, flags);
704 } else {
705 /* print counted ascii string */
706 PANSI_STRING pus = va_arg(args, PANSI_STRING);
707 if ((pus == NULL) || (pus->Buffer)) {
708 s = NULL;
709 len = -1;
710 } else {
711 s = pus->Buffer;
712 len = pus->Length;
713 }
714 result = string(f, s, len, field_width, precision, flags);
715 }
716 if (result < 0)
717 return -1;
718 done += result;
719 continue;
720
721 case L'e': /* finished */
722 case L'E':
723 case L'f':
724 case L'g':
725 case L'G':
726 _double = (double)va_arg(args, double);
727
728 if ( _isnan(_double) ) {
729 sw = L"Nan";
730 len = 3;
731 while ( len > 0 ) {
732 if (putwc(*sw++,f) == WEOF)
733 return -1;
734 done++;
735 len --;
736 }
737 } else if ( _isinf(_double) < 0 ) {
738 sw = L"-Inf";
739 len = 4;
740 while ( len > 0 ) {
741 if (putwc(*sw++,f) == WEOF)
742 return -1;
743 done++;
744 len --;
745 }
746 } else if ( _isinf(_double) > 0 ) {
747 sw = L"+Inf";
748 len = 4;
749 while ( len > 0 ) {
750 if (putwc(*sw++,f) == WEOF)
751 return -1;
752 done++;
753 len --;
754 }
755 } else {
756 if ( precision == -1 )
757 precision = 6;
758 result = numberf(f,_double,*fmt,field_width,precision,flags);
759 if (result < 0)
760 return -1;
761 done += result;
762 }
763 continue;
764
765 case L'p':
766 if (field_width == -1) {
767 field_width = 2*sizeof(void *);
768 flags |= ZEROPAD;
769 }
770 result = number(f,
771 (unsigned long) va_arg(args, void *), 16,
772 field_width, precision, flags);
773 if (result < 0)
774 return -1;
775 done += result;
776 continue;
777
778 case L'n':
779 if (qualifier == L'l') {
780 long * ip = va_arg(args, long *);
781 *ip = 0;
782 } else {
783 int * ip = va_arg(args, int *);
784 *ip = 0;
785 }
786 continue;
787
788 /* integer number formats - set up the flags and "break" */
789 case L'o':
790 base = 8;
791 break;
792
793 case L'b':
794 base = 2;
795 break;
796
797 case L'X':
798 flags |= LARGE;
799 case L'x':
800 base = 16;
801 break;
802
803 case L'd':
804 case L'i':
805 flags |= SIGN;
806 case L'u':
807 break;
808
809 default:
810 if (*fmt != L'%')
811 {
812 if (putwc(L'%', f) == WEOF)
813 return -1;
814 done++;
815 }
816 if (*fmt)
817 {
818 if (putwc(*fmt, f) == WEOF)
819 return -1;
820 done++;
821 }
822 else
823 --fmt;
824 continue;
825 }
826
827 if (qualifier == L'I')
828 num = va_arg(args, ULONGLONG);
829 else if (qualifier == L'l') {
830 if (flags & SIGN)
831 num = va_arg(args, long);
832 else
833 num = va_arg(args, unsigned long);
834 }
835 else if (qualifier == L'h') {
836 if (flags & SIGN)
837 num = va_arg(args, int);
838 else
839 num = va_arg(args, unsigned int);
840 }
841 else if (flags & SIGN)
842 num = va_arg(args, int);
843 else
844 num = va_arg(args, unsigned int);
845 result = number(f, num, base, field_width, precision, flags);
846 if (result < 0)
847 return -1;
848 done += result;
849 }
850 //putwc(L'\0',f);
851 return done;
852 }
853
854 /* EOF */