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