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