:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[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
15 __vfprintf (FILE *fp, const char *fmt0, va_list args);
16
17 int
18 vfprintf(FILE *f, const char *fmt, va_list ap)
19 {
20   int len;
21   char localbuf[BUFSIZ];
22
23 #if 0
24   __fileno_lock(fileno(f));
25 #endif
26   if (f->_flag & _IONBF)
27   {
28     f->_flag &= ~_IONBF;
29     f->_ptr = f->_base = localbuf;
30     f->_bufsiz = BUFSIZ;
31     len = __vfprintf(f,fmt, ap);
32     (void)fflush(f);
33     f->_flag |= _IONBF;
34     f->_base = NULL;
35     f->_bufsiz = 0;
36     f->_cnt = 0;
37   }
38   else
39     len = __vfprintf(f,fmt, ap);
40 #if 0
41   __fileno_unlock(fileno(f));
42 #endif
43   return (ferror(f) ? EOF : len);
44 }
45
46
47 /*
48  *  linux/lib/vsprintf.c
49  *
50  *  Copyright (C) 1991, 1992  Linus Torvalds
51  */
52
53 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
54 /*
55  * Wirzenius wrote this portably, Torvalds fucked it up :-)
56  */
57
58 /*
59  * Appropiated for the reactos kernel, March 1998 -- David Welch
60  */
61
62 #include <msvcrt/stdarg.h>
63
64 #include <msvcrt/ctype.h>
65 #include <msvcrt/string.h>
66 #include <msvcrt/stdio.h>
67 #include <msvcrt/string.h>
68 #include <msvcrt/math.h>
69 #include <msvcrt/internal/ieee.h>
70
71
72 #define ZEROPAD         1       /* pad with zero */
73 #define SIGN            2       /* unsigned/signed long */
74 #define PLUS            4       /* show plus */
75 #define SPACE           8       /* space if plus */
76 #define LEFT            16      /* left justified */
77 #define SPECIAL         32      /* 0x */
78 #define LARGE           64      /* use 'ABCDEF' instead of 'abcdef' */
79 #define ZEROTRUNC       128     /* truncate zero 's */
80
81
82 static int skip_atoi(const char **s)
83 {
84         int i=0;
85
86         while (isdigit(**s))
87                 i = i*10 + *((*s)++) - '0';
88         return i;
89 }
90
91
92 static int do_div(long long *n,int base)
93 {
94         int __res = ((unsigned long long) *n) % (unsigned) base;
95         *n = ((unsigned long long) *n) / (unsigned) base;
96         return __res;
97 }
98
99
100 static int number(FILE * f, long long num, int base, int size, int precision ,int type)
101 {
102         char c,sign,tmp[66];
103         const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
104         int i, done = 0;
105
106         if (type & LARGE)
107                 digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
108         if (type & LEFT)
109                 type &= ~ZEROPAD;
110         if (base < 2 || base > 36)
111                 return done;
112         c = (type & ZEROPAD) ? '0' : ' ';
113         sign = 0;
114         if (type & SIGN) {
115                 if (num < 0) {
116                         sign = '-';
117                         num = -num;
118                         size--;
119                 } else if (type & PLUS) {
120                         sign = '+';
121                         size--;
122                 } else if (type & SPACE) {
123                         sign = ' ';
124                         size--;
125                 }
126         }
127         if (type & SPECIAL) {
128                 if (base == 16)
129                         size -= 2;
130                 else if (base == 8)
131                         size--;
132         }
133         i = 0;
134         if (num == 0)
135                 tmp[i++]='0';
136         else while (num != 0)
137                 tmp[i++] = digits[do_div(&num,base)];
138         if (i > precision)
139                 precision = i;
140         size -= precision;
141         if (!(type&(ZEROPAD+LEFT)))
142                 while(size-->0)
143                 {
144                         if (putc(' ',f) == EOF)
145                                 return -1;
146                         done++;
147                 }
148         if (sign)
149         {
150                 if (putc(sign,f) == EOF)
151                         return -1;
152                 done++;
153         }
154         if (type & SPECIAL) {
155                 if (base==8) {
156                         if (putc('0',f) == EOF)
157                                 return -1;
158                         done++;
159                 }
160                 else if (base==16) {
161                         if (putc('0', f) == EOF)
162                                 return -1;
163                         done++;
164                         if (putc(digits[33],f) == EOF)
165                                 return -1;
166                         done++;
167                 }
168         }
169         if (!(type & LEFT))
170                 while (size-- > 0)
171                 {
172                         if (putc(c,f) == EOF)
173                                 return -1;
174                         done++;
175                 }
176         while (i < precision--)
177         {
178                 if (putc('0', f) == EOF)
179                         return -1;
180                 done++;
181         }
182         while (i-- > 0)
183         {
184                 if (putc(tmp[i],f) == EOF)
185                         return -1;
186                 done++;
187         }
188         while (size-- > 0)
189         {
190                 if (putc(' ', f) == EOF)
191                         return -1;
192                 done++;
193         }
194         return done;
195 }
196
197
198 static int numberf(FILE * f, double __n, char exp_sign,  int size, int precision, int type)
199 {
200         double exponent = 0.0;
201         double e;
202         long ie;
203
204         //int x;
205         char *buf, *tmp;
206         int i = 0;
207         int j = 0;
208         //int k = 0;
209
210         double frac, intr;
211         double p;
212         char sign;
213         char c;
214         char ro = 0;
215         int result, done = 0;
216
217         double_t *n = (double_t *)&__n;
218
219         if ( exp_sign == 'g' || exp_sign == 'G' || exp_sign == 'e' || exp_sign == 'E' ) {
220                 ie = ((unsigned int)n->exponent - (unsigned int)0x3ff);
221                 exponent = ie/3.321928;
222         }
223
224         if ( exp_sign == 'g' || exp_sign == 'G' ) {
225                 type |= ZEROTRUNC;
226                 if ( exponent < -4 || fabs(exponent) >= precision )
227                          exp_sign -= 2; // g -> e and G -> E
228         }
229
230         if ( exp_sign == 'e' ||  exp_sign == 'E' ) {
231                 frac = modf(exponent,&e);
232                 if ( frac > 0.5 )
233                         e++;
234                 else if (  frac < -0.5  )
235                         e--;
236
237                 result = numberf(f,__n/pow(10.0L,e),'f',size-4, precision, type);
238                 if (result < 0)
239                         return -1;
240                 done += result;
241                 if (putc( exp_sign,f) == EOF)
242                         return -1;
243                 done++;
244                 size--;
245                 ie = (long)e;
246                 type = LEFT | PLUS;
247                 if ( ie < 0 )
248                         type |= SIGN;
249
250                 result = number(f,ie, 10,2, 2,type );
251                 if (result < 0)
252                         return -1;
253                 done += result;
254                 return done;
255         }
256
257         if ( exp_sign == 'f' ) {
258                 buf = alloca(4096);
259                 if (type & LEFT) {
260                         type &= ~ZEROPAD;
261                 }
262
263                 c = (type & ZEROPAD) ? '0' : ' ';
264                 sign = 0;
265                 if (type & SIGN) {
266                         if (__n < 0) {
267                                 sign = '-';
268                                 __n = fabs(__n);
269                                 size--;
270                         } else if (type & PLUS) {
271                                 sign = '+';
272                                 size--;
273                         } else if (type & SPACE) {
274                                 sign = ' ';
275                                 size--;
276                         }
277                 }
278
279                 frac = modf(__n,&intr);
280
281                 // # flags forces a . and prevents trucation of trailing zero's
282
283                 if ( precision > 0 ) {
284                         //frac = modfl(__n,&intr);
285                         i = precision-1;
286                         while (  i >= 0  ) {
287                                 frac*=10.0L;
288                                 frac = modf(frac, &p);
289                                 buf[i] = (int)p + '0';
290                                 i--;
291                         }
292                         i = precision;
293                         size -= precision;
294
295                         ro = 0;
296                         if ( frac > 0.5 ) {
297                                 ro = 1;
298                         }
299
300                         if ( precision >= 1 || type & SPECIAL) {
301                                 buf[i++] = '.';
302                                 size--;
303                         }
304                 }
305
306                 if ( intr == 0.0 ) {
307                         buf[i++] = '0';
308                         size--;
309                 }
310                 else {
311                         while ( intr > 0.0 ) {
312                                 intr/=10.0L;
313                                 p = modf(intr, &intr);
314
315                                 p *=10;
316
317                                 buf[i++] = (int)p + '0';
318                                 size--;
319                         }
320                 }
321
322                 j = 0;
323                 while ( j < i && ro == 1) {
324                         if ( buf[j] >= '0' && buf[j] <= '8' ) {
325                                 buf[j]++;
326                                 ro = 0;
327                         }
328                         else if ( buf[j] == '9' ) {
329                                 buf[j] = '0';
330                         }
331                         j++;
332                 }
333                 if ( ro == 1 )
334                         buf[i++] = '1';
335
336                 buf[i] = 0;
337
338                 size -= precision;
339                 if (!(type&(ZEROPAD+LEFT)))
340                         while(size-->0)
341                         {
342                                 if (putc(' ',f) == EOF)
343                                         return -1;
344                                 done++;
345                         }
346                 if (sign)
347                 {
348                         if (putc( sign,f) == EOF)
349                                 return -1;
350                         done++;
351                 }
352
353                 if (!(type&(ZEROPAD+LEFT)))
354                         while(size-->0)
355                         {
356                                 if (putc(' ',f) == EOF)
357                                         return -1;
358                                 done++;
359                         }
360                 if (type & SPECIAL) {
361                 }
362
363                 if (!(type & LEFT))
364                         while (size-- > 0)
365                         {
366                                 if (putc(c,f) == EOF)
367                                         return -1;
368                                 done++;
369                         }
370
371                 tmp = buf;
372                 if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) {
373                         j = 0;
374                         while ( j < i && ( *tmp == '0' || *tmp == '.' )) {
375                                         tmp++;
376                                         i--;
377                         }
378                 }
379 //              else
380 //                      while (i < precision--)
381 //                              putc('0', f);
382                 while (i-- > 0)
383                 {
384                         if (putc(tmp[i],f) == EOF)
385                                 return -1;
386                         done++;
387                 }
388                 while (size-- > 0)
389                 {
390                         if (putc(' ', f) == EOF)
391                                 return -1;
392                         done++;
393                 }
394         }
395         return done;
396 }
397
398
399 static int numberfl(FILE * f, long double __n, char exp_sign,  int size, int precision, int type)
400 {
401         long double exponent = 0.0;
402         long double e;
403         long ie;
404
405         //int x;
406         char *buf, *tmp;
407         int i = 0;
408         int j = 0;
409         //int k = 0;
410
411         long double frac, intr;
412         long double p;
413         char sign;
414         char c;
415         char ro = 0;
416
417         int result, done = 0;
418
419         long_double_t *n = (long_double_t *)&__n;
420
421         if ( exp_sign == 'g' || exp_sign == 'G' || exp_sign == 'e' || exp_sign == 'E' ) {
422                 ie = ((unsigned int)n->exponent - (unsigned int)0x3fff);
423                 exponent = ie/3.321928;
424         }
425
426         if ( exp_sign == 'g' || exp_sign == 'G' ) {
427                 type |= ZEROTRUNC;
428                 if ( exponent < -4 || fabs(exponent) >= precision ) 
429                          exp_sign -= 2; // g -> e and G -> E
430         }
431
432         if ( exp_sign == 'e' || exp_sign == 'E' ) {
433                 frac = modfl(exponent,&e);
434                 if ( frac > 0.5 )
435                         e++;
436                 else if ( frac < -0.5 )
437                         e--;
438
439                 result = numberf(f,__n/powl(10.0L,e),'f',size-4, precision, type);
440                 if (result < 0)
441                         return -1;
442                 done += result;
443                 if (putc( exp_sign,f) == EOF)
444                         return -1;
445                 done++;
446                 size--;
447                 ie = (long)e;
448                 type = LEFT | PLUS;
449                 if ( ie < 0 )
450                         type |= SIGN;
451
452                 result = number(f,ie, 10,2, 2,type );
453                 if (result < 0)
454                         return -1;
455                 done += result;
456                 return done;
457         }
458
459         if ( exp_sign == 'f' ) {
460                 
461                 buf = alloca(4096);
462                 if (type & LEFT) {
463                         type &= ~ZEROPAD;
464                 }
465
466                 c = (type & ZEROPAD) ? '0' : ' ';
467                 sign = 0;
468                 if (type & SIGN) {
469                         if (__n < 0) {
470                                 sign = '-';
471                                 __n = fabs(__n);
472                                 size--;
473                         } else if (type & PLUS) {
474                                 sign = '+';
475                                 size--;
476                         } else if (type & SPACE) {
477                                 sign = ' ';
478                                 size--;
479                         }
480                 }
481
482                 frac = modfl(__n,&intr);
483
484                 // # flags forces a . and prevents trucation of trailing zero's
485                 if ( precision > 0 ) {
486                         //frac = modfl(__n,&intr);
487
488                         i = precision-1;
489                         while ( i >= 0  ) {
490                                 frac*=10.0L;
491                                 frac = modfl((long double)frac, &p);
492                                 buf[i] = (int)p + '0';
493                                 i--;
494                         }
495                         i = precision;
496                         size -= precision;
497
498                         ro = 0;
499                         if ( frac > 0.5 ) {
500                                 ro = 1;
501                         }
502
503                         if ( precision >= 1 || type & SPECIAL) {
504                                 buf[i++] = '.';
505                                 size--;
506                         }
507                 }
508
509                 if ( intr == 0.0 ) {
510                         buf[i++] = '0';
511                         size--;
512                 }
513                 else {
514                         while ( intr > 0.0 ) {
515                                 intr/=10.0L;
516                                 p = modfl(intr, &intr);
517
518                                 p *=10;
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         unsigned long long 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, unsigned long long);
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 */