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