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