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