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