update for HEAD-2003021201
[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                                 intr/=10.0L;
311                                 p = modf(intr, &intr);
312
313                                 p *=10;
314
315                                 buf[i++] = (int)p + '0';
316                                 size--;
317                         }
318                 }
319
320                 j = 0;
321                 while ( j < i && ro == 1) {
322                         if ( buf[j] >= '0' && buf[j] <= '8' ) {
323                                 buf[j]++;
324                                 ro = 0;
325                         }
326                         else if ( buf[j] == '9' ) {
327                                 buf[j] = '0';
328                         }
329                         j++;
330                 }
331                 if ( ro == 1 )
332                         buf[i++] = '1';
333
334                 buf[i] = 0;
335
336                 size -= precision;
337                 if (!(type&(ZEROPAD+LEFT)))
338                         while(size-->0)
339                         {
340                                 if (putc(' ',f) == EOF)
341                                         return -1;
342                                 done++;
343                         }
344                 if (sign)
345                 {
346                         if (putc( sign,f) == EOF)
347                                 return -1;
348                         done++;
349                 }
350
351                 if (!(type&(ZEROPAD+LEFT)))
352                         while(size-->0)
353                         {
354                                 if (putc(' ',f) == EOF)
355                                         return -1;
356                                 done++;
357                         }
358                 if (type & SPECIAL) {
359                 }
360
361                 if (!(type & LEFT))
362                         while (size-- > 0)
363                         {
364                                 if (putc(c,f) == EOF)
365                                         return -1;
366                                 done++;
367                         }
368
369                 tmp = buf;
370                 if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) {
371                         j = 0;
372                         while ( j < i && ( *tmp == '0' || *tmp == '.' )) {
373                                         tmp++;
374                                         i--;
375                         }
376                 }
377 //              else
378 //                      while (i < precision--)
379 //                              putc('0', f);
380                 while (i-- > 0)
381                 {
382                         if (putc(tmp[i],f) == EOF)
383                                 return -1;
384                         done++;
385                 }
386                 while (size-- > 0)
387                 {
388                         if (putc(' ', f) == EOF)
389                                 return -1;
390                         done++;
391                 }
392         }
393         return done;
394 }
395
396
397 static int numberfl(FILE * f, long double __n, char exp_sign,  int size, int precision, int type)
398 {
399         long double exponent = 0.0;
400         long double e;
401         long ie;
402
403         //int x;
404         char *buf, *tmp;
405         int i = 0;
406         int j = 0;
407         //int k = 0;
408
409         long double frac, intr;
410         long double p;
411         char sign;
412         char c;
413         char ro = 0;
414
415         int result, done = 0;
416
417         long_double_t *n = (long_double_t *)&__n;
418
419         if ( exp_sign == 'g' || exp_sign == 'G' || exp_sign == 'e' || exp_sign == 'E' ) {
420                 ie = ((unsigned int)n->exponent - (unsigned int)0x3fff);
421                 exponent = ie/3.321928;
422         }
423
424         if ( exp_sign == 'g' || exp_sign == 'G' ) {
425                 type |= ZEROTRUNC;
426                 if ( exponent < -4 || fabs(exponent) >= precision ) 
427                          exp_sign -= 2; // g -> e and G -> E
428         }
429
430         if ( exp_sign == 'e' || exp_sign == 'E' ) {
431                 frac = modfl(exponent,&e);
432                 if ( frac > 0.5 )
433                         e++;
434                 else if ( frac < -0.5 )
435                         e--;
436
437                 result = numberf(f,__n/powl(10.0L,e),'f',size-4, precision, type);
438                 if (result < 0)
439                         return -1;
440                 done += result;
441                 if (putc( exp_sign,f) == EOF)
442                         return -1;
443                 done++;
444                 size--;
445                 ie = (long)e;
446                 type = LEFT | PLUS;
447                 if ( ie < 0 )
448                         type |= SIGN;
449
450                 result = number(f,ie, 10,2, 2,type );
451                 if (result < 0)
452                         return -1;
453                 done += result;
454                 return done;
455         }
456
457         if ( exp_sign == 'f' ) {
458                 
459                 buf = alloca(4096);
460                 if (type & LEFT) {
461                         type &= ~ZEROPAD;
462                 }
463
464                 c = (type & ZEROPAD) ? '0' : ' ';
465                 sign = 0;
466                 if (type & SIGN) {
467                         if (__n < 0) {
468                                 sign = '-';
469                                 __n = fabs(__n);
470                                 size--;
471                         } else if (type & PLUS) {
472                                 sign = '+';
473                                 size--;
474                         } else if (type & SPACE) {
475                                 sign = ' ';
476                                 size--;
477                         }
478                 }
479
480                 frac = modfl(__n,&intr);
481
482                 // # flags forces a . and prevents trucation of trailing zero's
483                 if ( precision > 0 ) {
484                         //frac = modfl(__n,&intr);
485
486                         i = precision-1;
487                         while ( i >= 0  ) {
488                                 frac*=10.0L;
489                                 frac = modfl((long double)frac, &p);
490                                 buf[i] = (int)p + '0';
491                                 i--;
492                         }
493                         i = precision;
494                         size -= precision;
495
496                         ro = 0;
497                         if ( frac > 0.5 ) {
498                                 ro = 1;
499                         }
500
501                         if ( precision >= 1 || type & SPECIAL) {
502                                 buf[i++] = '.';
503                                 size--;
504                         }
505                 }
506
507                 if ( intr == 0.0 ) {
508                         buf[i++] = '0';
509                         size--;
510                 }
511                 else {
512                         while ( intr > 0.0 ) {
513                                 intr/=10.0L;
514                                 p = modfl(intr, &intr);
515
516                                 p *=10;
517
518                                 buf[i++] = (int)p + '0';
519                                 size--;
520                         }
521                 }
522
523                 j = 0;
524                 while ( j < i && ro == 1) {
525                         if ( buf[j] >= '0' && buf[j] <= '8' ) {
526                                 buf[j]++;
527                                 ro = 0;
528                         }
529                         else if ( buf[j] == '9' ) {
530                                 buf[j] = '0';
531                         }
532                         j++;
533                 }
534                 if ( ro == 1 )
535                         buf[i++] = '1';
536
537                 buf[i] = 0;
538
539                 size -= precision;
540                 if (!(type&(ZEROPAD+LEFT)))
541                         while(size-->0)
542                         {
543                                 if (putc(' ',f) == EOF)
544                                         return -1;
545                                 done++;
546                         }
547                 if (sign)
548                 {
549                         if (putc(sign,f) == EOF)
550                                 return -1;
551                         done++;
552                 }
553
554                 if (!(type&(ZEROPAD+LEFT)))
555                         while(size-->0)
556                         {
557                                 if (putc(' ',f) == EOF)
558                                         return -1;
559                                 done++;
560                         }
561                 if (type & SPECIAL) {
562                 }
563
564                 if (!(type & LEFT))
565                         while (size-- > 0)
566                         {
567                                 if (putc(c,f) == EOF)
568                                         return -1;
569                                 done++;
570                         }
571                 tmp = buf;
572                 if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) {
573                         j = 0;
574                         while ( j < i && ( *tmp == '0' || *tmp == '.' )) {
575                                 tmp++;
576                                 i--;
577                         }
578                 }
579 //              else
580 //                      while (i < precision--)
581 //                                  putc( '0', f);
582                 while (i-- > 0)
583                 {
584                         if ( putc(tmp[i],f) == EOF)
585                                 return -1;
586                         done++;
587                 }
588                 while (size-- > 0)
589                 {
590                         if (putc(' ', f) == EOF)
591                                 return -1;
592                         done++;
593                 }
594         }
595         return done;
596 }
597
598 static int string(FILE *f, const char* s, int len, int field_width, int precision, int flags)
599 {
600         int i, done = 0;
601         if (s == NULL)
602         {
603                 s = "<NULL>";
604                 len = 6;
605         }
606         else
607         {
608                 if (len == -1)
609                 {
610                         len = 0;
611                         while (s[len] && (unsigned int)len < (unsigned int)precision)
612                                 len++;
613                 }
614                 else
615                 {
616                         if ((unsigned int)len > (unsigned int)precision)
617                                 len = precision;
618                 }
619         }
620         if (!(flags & LEFT))
621                 while (len < field_width--)
622                 {
623                         if (putc(' ', f) == EOF)
624                                 return -1;
625                         done++;
626                 }
627         for (i = 0; i < len; ++i)
628         {
629                 if (putc(*s++, f) == EOF)
630                         return -1;
631                 done++;
632         }
633         while (len < field_width--)
634         {
635                 if (putc(' ', f) == EOF)
636                         return -1;
637                 done++;
638         }
639         return done;
640 }
641
642 static int stringw(FILE *f, const wchar_t* sw, int len, int field_width, int precision, int flags)
643 {
644         int i, done = 0;
645         if (sw == NULL)
646         {
647                 sw = L"<NULL>";
648                 len = 6;
649         }
650         else
651         {
652                 if (len == -1)
653                 {
654                         len = 0;
655                         while (sw[len] && (unsigned int)len < (unsigned int)precision)
656                                 len++;
657                 }
658                 else
659                 {
660                         if ((unsigned int)len > (unsigned int)precision)
661                                 len = precision;
662                 }
663         }
664         if (!(flags & LEFT))
665                 while (len < field_width--)
666                 {
667                         if (putc(' ', f) == EOF)
668                                 return -1;
669                         done++;
670                 }
671         for (i = 0; i < len; ++i)
672         {
673                 if (putc((unsigned char)(*sw++), f) == EOF)
674                         return -1;
675                 done++;
676         }
677         while (len < field_width--)
678         {
679                 if (putc(' ', f) == EOF)
680                         return -1;
681                 done++;
682         }
683         return done;
684 }
685
686 int __vfprintf(FILE *f, const char *fmt, va_list args)
687 {
688         int len;
689         ULONGLONG num;
690         int i, base;
691         long double _ldouble;
692         double _double;
693         const char *s;
694         const short int* sw;
695         int result, done = 0;
696
697         int flags;              /* flags to number() */
698
699         int field_width;        /* width of output field */
700         int precision;          /* min. # of digits for integers; max
701                                    number of chars for from string */
702         int qualifier = 0;      /* 'h', 'l', 'L' or 'I64' for integer fields */
703
704         for (; *fmt ; ++fmt) {
705                 if (*fmt != '%') {
706                         if (putc(*fmt,f) == EOF)
707                                 return -1;
708                         done++;
709                         continue;
710                 }
711
712                 /* process flags */
713                 flags = 0;
714                 repeat:
715                         ++fmt;          /* this also skips first '%' */
716                         switch (*fmt) {
717                                 case '-': flags |= LEFT; goto repeat;
718                                 case '+': flags |= PLUS; goto repeat;
719                                 case ' ': flags |= SPACE; goto repeat;
720                                 case '#': flags |= SPECIAL; goto repeat;
721                                 case '0': flags |= ZEROPAD; goto repeat;
722                                 }
723
724                 /* get field width */
725                 field_width = -1;
726                 if (isdigit(*fmt))
727                         field_width = skip_atoi(&fmt);
728                 else if (*fmt == '*') {
729                         ++fmt;
730                         /* it's the next argument */
731                         field_width = va_arg(args, int);
732                         if (field_width < 0) {
733                                 field_width = -field_width;
734                                 flags |= LEFT;
735                         }
736                 }
737
738                 /* get the precision */
739                 precision = -1;
740                 if (*fmt == '.') {
741                         ++fmt;
742                         if (isdigit(*fmt))
743                                 precision = skip_atoi(&fmt);
744                         else if (*fmt == '*') {
745                                 ++fmt;
746                                 /* it's the next argument */
747                                 precision = va_arg(args, int);
748                         }
749                         if (precision < 0)
750                                 precision = 0;
751                 }
752
753                 /* get the conversion qualifier */
754                 qualifier = 0;
755                 // %Z can be just stand alone or as size_t qualifier
756                 if ( *fmt == 'Z' ) {
757                         qualifier = *fmt;
758                         switch ( *(fmt+1)) {
759                                 case 'o':
760                                 case 'b':
761                                 case 'X':
762                                 case 'x':
763                                 case 'd':
764                                 case 'i':
765                                 case 'u':
766                                         ++fmt;
767                                         break;
768                                 default:
769                                         break;
770                         }
771                 } else if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'w') {
772                         qualifier = *fmt;
773                         ++fmt;
774                 } else if (*fmt == 'I' && *(fmt+1) == '6' && *(fmt+2) == '4') {
775                         qualifier = *fmt;
776                         fmt += 3;
777                 }
778
779                 // go fine with ll instead of L
780                 if ( *fmt == 'l' ) {
781                         ++fmt;
782                         qualifier = 'L';
783                 }
784
785                 /* default base */
786                 base = 10;
787
788                 switch (*fmt) {
789                 case 'c':
790                         if (!(flags & LEFT))
791                                 while (--field_width > 0)
792                                 {
793                                         if (putc(' ', f) == EOF)
794                                                 return -1;
795                                         done++;
796                                 }
797                         if (qualifier == 'l' || qualifier == 'w')
798                         {
799                                 if (putc((unsigned char)(wchar_t) va_arg(args, int), f) == EOF)
800                                         return -1;
801                                 done++;
802                         }
803                         else
804                         {
805                                 if (putc((unsigned char) va_arg(args, int), f) == EOF)
806                                         return -1;
807                                 done++;
808                         }
809                         while (--field_width > 0)
810                         {
811                                 if (putc(' ', f) == EOF)
812                                         return -1;
813                                 done++;
814                         }
815                         continue;
816
817                 case 'C':
818                         if (!(flags & LEFT))
819                                 while (--field_width > 0)
820                                 {
821                                         if (putc(' ', f) == EOF)
822                                                 return -1;
823                                         done++;
824                                 }
825                         if (qualifier == 'h')
826                         {
827                                 if (putc((unsigned char) va_arg(args, int), f) == EOF)
828                                         return -1;
829                                 done++;
830                         }
831                         else
832                         {
833                                 if (putc((unsigned char)(wchar_t) va_arg(args, int), f) == EOF)
834                                         return -1;
835                                 done++;
836                         }
837                         while (--field_width > 0)
838                         {
839                                 if (putc(' ', f) == EOF)
840                                         return -1;
841                                 done++;
842                         }
843                         continue;
844
845                 case 's':
846                         if (qualifier == 'l' || qualifier == 'w') {
847                                 /* print unicode string */
848                                 sw = va_arg(args, wchar_t *);
849                                 result = stringw(f, sw, -1, field_width, precision, flags);
850                         } else {
851                                 /* print ascii string */
852                                 s = va_arg(args, char *);
853                                 result = string(f, s, -1, field_width, precision, flags);
854                         }
855                         if (result < 0)
856                                 return -1;
857                         done += result;
858                         continue;
859
860                 case 'S':
861                         if (qualifier == 'h') {
862                                 /* print ascii string */
863                                 s = va_arg(args, char *);
864                                 result = string(f, s, -1, field_width, precision, flags);
865                         } else {
866                                 /* print unicode string */
867                                 sw = va_arg(args, wchar_t *);
868                                 result = stringw(f, sw, -1, field_width, precision, flags);
869                         }
870                         if (result < 0)
871                                 return -1;
872                         done += result;
873                         continue;
874
875                 case 'Z':
876                         if (qualifier == 'w') {
877                                 /* print counted unicode string */
878                                 PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING);
879                                 if ((pus == NULL) || (pus->Buffer == NULL)) {
880                                         sw = NULL;
881                                         len = -1;
882                                 } else {
883                                         sw = pus->Buffer;
884                                         len = pus->Length / sizeof(WCHAR);
885                                 }
886                                 result = stringw(f, sw, len, field_width, precision, flags);
887                         } else {
888                                 /* print counted ascii string */
889                                 PANSI_STRING pas = va_arg(args, PANSI_STRING);
890                                 if ((pas == NULL) || (pas->Buffer == NULL)) {
891                                         s = NULL;
892                                         len = -1;
893                                 } else {
894                                         s = pas->Buffer;
895                                         len = pas->Length;
896                                 }
897                                 result = string(f, s, -1, field_width, precision, flags);
898                         }
899                         if (result < 0)
900                                 return -1;
901                         done += result;
902                         continue;
903
904                 case 'e':
905                 case 'E':
906                 case 'f':
907                 case 'g':
908                 case 'G':
909                         if (qualifier == 'l' || qualifier == 'L' ) {
910                                 _ldouble = va_arg(args, long double);
911                         
912                                 if ( _isnanl(_ldouble) ) {
913                                         s = "Nan";
914                                         len = 3;
915                                         while ( len > 0 ) {
916                                                 if (putc(*s++,f) == EOF)
917                                                         return -1;
918                                                 done++;
919                                                 len --;
920                                         }
921                                 }
922                                 else if ( _isinfl(_ldouble) < 0 ) {
923                                         s = "-Inf";
924                                         len = 4;
925                                         while ( len > 0 ) {
926                                                 if (putc(*s++,f) == EOF)
927                                                         return -1;
928                                                 done++;
929                                                 len --;
930                                         }
931                                 }
932                                 else if ( _isinfl(_ldouble) > 0 ) {
933                                         s = "+Inf";
934                                         len = 4;
935                                         while ( len > 0 ) {
936                                                 if (putc(*s++,f) == EOF)
937                                                         return -1;
938                                                 done++;
939                                                 len --;
940                                         }
941                                 } else {
942                                         if ( precision == -1 )
943                                                 precision = 6;
944                                         result = numberfl(f,_ldouble,*fmt,field_width,precision,flags);
945                                         if (result < 0)
946                                                 return -1;
947                                         done += result;
948                                 }
949                         } else {
950                                 _double = (double)va_arg(args, double);
951
952                                 if ( _isnan(_double) ) {
953                                         s = "Nan";
954                                         len = 3;
955                                         while ( len > 0 ) {
956                                                 if (putc(*s++,f) == EOF)
957                                                         return -1;
958                                                 done++;
959                                                 len --;
960                                         }
961                                 } else if ( _isinf(_double) < 0 ) {
962                                         s = "-Inf";
963                                         len = 4;
964                                         while ( len > 0 ) {
965                                                 if (putc(*s++,f) == EOF)
966                                                         return -1;
967                                                 done++;
968                                                 len --;
969                                         }
970                                 } else if ( _isinf(_double) > 0 ) {
971                                         s = "+Inf";
972                                         len = 4;
973                                         while ( len > 0 ) {
974                                                 if (putc(*s++,f) == EOF)
975                                                         return -1;
976                                                 done++;
977                                                 len --;
978                                         }
979                                 } else {
980                                         if ( precision == -1 )
981                                                 precision = 6;
982                                         result = numberf(f,_double,*fmt,field_width,precision,flags);
983                                         if (result < 0)
984                                                 return -1;
985                                         done += result;
986                                 }
987                         }
988                         continue;
989
990                 case 'p':
991                         if (field_width == -1) {
992                                 field_width = 2*sizeof(void *);
993                                 flags |= ZEROPAD;
994                         }
995                         result = number(f,
996                                         (unsigned long) va_arg(args, void *), 16,
997                                         field_width, precision, flags);
998                         if (result < 0)
999                                 return -1;
1000                         done += result;
1001                         continue;
1002
1003                 case 'n':
1004                         if (qualifier == 'l') {
1005                                 long * ip = va_arg(args, long *);
1006                                 *ip = 0;
1007                         } else {
1008                                 int * ip = va_arg(args, int *);
1009                                 *ip = 0;
1010                         }
1011                         continue;
1012
1013                 /* integer number formats - set up the flags and "break" */
1014                 case 'o':
1015                         base = 8;
1016                         break;
1017
1018                 case 'b':
1019                         base = 2;
1020                         break;
1021
1022                 case 'X':
1023                         flags |= LARGE;
1024                 case 'x':
1025                         base = 16;
1026                         break;
1027
1028                 case 'd':
1029                 case 'i':
1030                         flags |= SIGN;
1031                 case 'u':
1032                         break;
1033
1034                 default:
1035                         if (*fmt != '%')
1036                         {
1037                                 if (putc('%', f) == EOF)
1038                                         return -1;
1039                                 done++;
1040                         }
1041                         if (*fmt)
1042                         {
1043                                 if (putc(*fmt, f) == EOF)
1044                                         return -1;
1045                                 done++;
1046                         }
1047                         else
1048                                 --fmt;
1049                         continue;
1050                 }
1051
1052                 if (qualifier == 'I')
1053                         num = va_arg(args, ULONGLONG);
1054                 else if (qualifier == 'l')
1055                         num = va_arg(args, unsigned long);
1056                 else if (qualifier == 'h') {
1057                         if (flags & SIGN)
1058                                 num = va_arg(args, int);
1059                         else
1060                                 num = va_arg(args, unsigned int);
1061                 }
1062                 else if (flags & SIGN)
1063                         num = va_arg(args, int);
1064                 else
1065                         num = va_arg(args, unsigned int);
1066                 result = number(f, num, base, field_width, precision, flags);
1067                 if (result < 0)
1068                         return -1;
1069                 done += result;
1070         }
1071         //putc('\0',f);
1072         return done;
1073 }
1074
1075 /* EOF */