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