Forward EnumDependentServicesA/W to services.exe.
[reactos.git] / reactos / tools / ssprintf.cpp
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15 */
16
17 #ifdef __FreeBSD__
18 # include <stdlib.h>
19 #else
20 # include <malloc.h>
21 #endif // __FreeBSD__
22 #include <math.h>
23 #include <float.h>
24 #include <assert.h>
25 #include "ssprintf.h"
26
27 #ifndef WIN32
28 #define _finite __finite
29 #define _isnan __isnan
30 inline int iswdigit ( wchar_t c )
31 {
32 return ( c >= L'0' && c <= L'9' );
33 }
34 #endif//WIN32
35
36 #ifdef __FreeBSD__
37 # define __isnan isnan
38 # define __finite finite
39 # define powl __builtin_powl
40 # define modfl __builtin_modfl
41 #endif // _FreeBSD__
42
43 #ifdef _MSC_VER
44 #define alloca _alloca
45 #endif//_MSC_VER
46
47 #ifdef _MSC_VER
48 typedef __int64 LONGLONG;
49 typedef unsigned __int64 ULONGLONG;
50 #else
51 typedef long long LONGLONG;
52 typedef unsigned long long ULONGLONG;
53 #endif
54
55 typedef struct {
56 unsigned int mantissa:23;
57 unsigned int exponent:8;
58 unsigned int sign:1;
59 } ieee_float_t;
60
61 typedef struct {
62 unsigned int mantissal:32;
63 unsigned int mantissah:20;
64 unsigned int exponent:11;
65 unsigned int sign:1;
66 } ieee_double_t;
67
68 typedef struct {
69 unsigned int mantissal:32;
70 unsigned int mantissah:32;
71 unsigned int exponent:15;
72 unsigned int sign:1;
73 unsigned int empty:16;
74 } ieee_long_double_t;
75
76 std::string
77 ssprintf ( const char* fmt, ... )
78 {
79 va_list arg;
80 va_start(arg, fmt);
81 std::string f = ssvprintf ( fmt, arg );
82 va_end(arg);
83 return f;
84 }
85
86 std::wstring
87 sswprintf ( const wchar_t* fmt, ... )
88 {
89 va_list arg;
90 va_start(arg, fmt);
91 std::wstring f = sswvprintf ( fmt, arg );
92 va_end(arg);
93 return f;
94 }
95
96 #define ZEROPAD 1 /* pad with zero */
97 #define SIGN 2 /* unsigned/signed long */
98 #define PLUS 4 /* show plus */
99 #define SPACE 8 /* space if plus */
100 #define LEFT 16 /* left justified */
101 #define SPECIAL 32 /* 0x */
102 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
103 #define ZEROTRUNC 128 /* truncate zero 's */
104
105
106 static int
107 skip_atoi(const char **s)
108 {
109 int i=0;
110
111 while (isdigit(**s))
112 i = i*10 + *((*s)++) - '0';
113 return i;
114 }
115
116 static int
117 skip_wtoi(const wchar_t **s)
118 {
119 int i=0;
120
121 while (iswdigit(**s))
122 i = i*10 + *((*s)++) - L'0';
123 return i;
124 }
125
126
127 static int
128 do_div(LONGLONG *n,int base)
129 {
130 int __res = ((ULONGLONG) *n) % (unsigned) base;
131 *n = ((ULONGLONG) *n) / (unsigned) base;
132 return __res;
133 }
134
135
136 static bool
137 number(std::string& f, LONGLONG num, int base, int size, int precision ,int type)
138 {
139 char c,sign,tmp[66];
140 const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
141 int i;
142
143 if (type & LARGE)
144 digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
145 if (type & LEFT)
146 type &= ~ZEROPAD;
147 if (base < 2 || base > 36)
148 return false;
149 c = (type & ZEROPAD) ? '0' : ' ';
150 sign = 0;
151 if (type & SIGN) {
152 if (num < 0) {
153 sign = '-';
154 num = -num;
155 size--;
156 } else if (type & PLUS) {
157 sign = '+';
158 size--;
159 } else if (type & SPACE) {
160 sign = ' ';
161 size--;
162 }
163 }
164 if (type & SPECIAL) {
165 if (base == 16)
166 size -= 2;
167 else if (base == 8)
168 size--;
169 }
170 i = 0;
171 if (num == 0)
172 tmp[i++]='0';
173 else while (num != 0)
174 tmp[i++] = digits[do_div(&num,base)];
175 if (i > precision)
176 precision = i;
177 size -= precision;
178 if (!(type&(ZEROPAD+LEFT)))
179 while(size-->0)
180 f += ' ';
181 if (sign)
182 f += sign;
183 if (type & SPECIAL)
184 {
185 if (base==8)
186 f += '0';
187 else if (base==16)
188 {
189 f += '0';
190 f += digits[33];
191 }
192 }
193 if (!(type & LEFT))
194 {
195 while (size-- > 0)
196 f += c;
197 }
198 while (i < precision--)
199 {
200 f += '0';
201 }
202 while (i-- > 0)
203 {
204 f += tmp[i];
205 }
206 while (size-- > 0)
207 {
208 f += ' ';
209 }
210 return true;
211 }
212
213 static bool
214 wnumber(std::wstring& f, LONGLONG num, int base, int size, int precision ,int type)
215 {
216 wchar_t c,sign,tmp[66];
217 const wchar_t *digits = L"0123456789abcdefghijklmnopqrstuvwxyz";
218 int i;
219
220 if (type & LARGE)
221 digits = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
222 if (type & LEFT)
223 type &= ~ZEROPAD;
224 if (base < 2 || base > 36)
225 return 0;
226 c = (type & ZEROPAD) ? L'0' : L' ';
227 sign = false;
228 if (type & SIGN) {
229 if (num < 0) {
230 sign = L'-';
231 num = -num;
232 size--;
233 } else if (type & PLUS) {
234 sign = L'+';
235 size--;
236 } else if (type & SPACE) {
237 sign = L' ';
238 size--;
239 }
240 }
241 if (type & SPECIAL) {
242 if (base == 16)
243 size -= 2;
244 else if (base == 8)
245 size--;
246 }
247 i = 0;
248 if (num == 0)
249 tmp[i++]=L'0';
250 else while (num != 0)
251 tmp[i++] = digits[do_div(&num,base)];
252 if (i > precision)
253 precision = i;
254 size -= precision;
255 if (!(type&(ZEROPAD+LEFT)))
256 while(size-->0)
257 f += L' ';
258 if (sign)
259 f += sign;
260 if (type & SPECIAL)
261 {
262 if (base==8)
263 f += L'0';
264 else if (base==16)
265 {
266 f += L'0';
267 f += digits[33];
268 }
269 }
270 if (!(type & LEFT))
271 {
272 while (size-- > 0)
273 f += c;
274 }
275 while (i < precision--)
276 {
277 f += L'0';
278 }
279 while (i-- > 0)
280 {
281 f += tmp[i];
282 }
283 while (size-- > 0)
284 {
285 f += L' ';
286 }
287 return true;
288 }
289
290
291 static bool
292 numberf(std::string& f, double __n, char exp_sign, int size, int precision, int type)
293 {
294 double exponent = 0.0;
295 double e;
296 long ie;
297
298 //int x;
299 char *buf, *tmp;
300 int i = 0;
301 int j = 0;
302 //int k = 0;
303
304 double frac, intr;
305 double p;
306 char sign;
307 char c;
308 char ro = 0;
309 int result;
310
311 union
312 {
313 double* __n;
314 ieee_double_t* n;
315 } n;
316
317 n.__n = &__n;
318
319 if ( exp_sign == 'g' || exp_sign == 'G' || exp_sign == 'e' || exp_sign == 'E' ) {
320 ie = ((unsigned int)n.n->exponent - (unsigned int)0x3ff);
321 exponent = ie/3.321928;
322 }
323
324 if ( exp_sign == 'g' || exp_sign == 'G' ) {
325 type |= ZEROTRUNC;
326 if ( exponent < -4 || fabs(exponent) >= precision )
327 exp_sign -= 2; // g -> e and G -> E
328 else
329 exp_sign = 'f';
330 }
331
332 if ( exp_sign == 'e' || exp_sign == 'E' ) {
333 frac = modf(exponent,&e);
334 if ( frac > 0.5 )
335 e++;
336 else if ( frac < -0.5 )
337 e--;
338
339 result = numberf(f,__n/pow(10.0L,(long double)e),'f',size-4, precision, type);
340 if (result < 0)
341 return false;
342 f += exp_sign;
343 size--;
344 ie = (long)e;
345 type = LEFT | PLUS;
346 if ( ie < 0 )
347 type |= SIGN;
348
349 result = number(f,ie, 10,2, 2,type );
350 if (result < 0)
351 return false;
352 return true;
353 }
354
355 if ( exp_sign == 'f' ) {
356 buf = (char*)alloca(4096);
357 if (type & LEFT) {
358 type &= ~ZEROPAD;
359 }
360
361 c = (type & ZEROPAD) ? '0' : ' ';
362 sign = 0;
363 if (type & SIGN) {
364 if (__n < 0) {
365 sign = '-';
366 __n = fabs(__n);
367 size--;
368 } else if (type & PLUS) {
369 sign = '+';
370 size--;
371 } else if (type & SPACE) {
372 sign = ' ';
373 size--;
374 }
375 }
376
377 frac = modf(__n,&intr);
378
379 // # flags forces a . and prevents trucation of trailing zero's
380
381 if ( precision > 0 ) {
382 //frac = modfl(__n,&intr);
383 i = precision-1;
384 while ( i >= 0 ) {
385 frac*=10.0L;
386 frac = modf(frac, &p);
387 buf[i] = (int)p + '0';
388 i--;
389 }
390 i = precision;
391 size -= precision;
392
393 ro = 0;
394 if ( frac > 0.5 ) {
395 ro = 1;
396 }
397
398 if ( precision >= 1 || type & SPECIAL) {
399 buf[i++] = '.';
400 size--;
401 }
402 }
403
404 if ( intr == 0.0 ) {
405 buf[i++] = '0';
406 size--;
407 }
408 else {
409 while ( intr > 0.0 ) {
410 p = intr;
411 intr/=10.0L;
412 modf(intr, &intr);
413
414 p -= 10.0*intr;
415
416 buf[i++] = (int)p + '0';
417 size--;
418 }
419 }
420
421 j = 0;
422 while ( j < i && ro == 1) {
423 if ( buf[j] >= '0' && buf[j] <= '8' ) {
424 buf[j]++;
425 ro = 0;
426 }
427 else if ( buf[j] == '9' ) {
428 buf[j] = '0';
429 }
430 j++;
431 }
432 if ( ro == 1 )
433 buf[i++] = '1';
434
435 buf[i] = 0;
436
437 size -= precision;
438 if (!(type&(ZEROPAD+LEFT)))
439 {
440 while(size-->0)
441 f += ' ';
442 }
443 if (sign)
444 {
445 f += sign;
446 }
447
448 if (!(type&(ZEROPAD+LEFT)))
449 while(size-->0)
450 {
451 f += ' ';
452 }
453 if (type & SPECIAL) {
454 }
455
456 if (!(type & LEFT))
457 while (size-- > 0)
458 {
459 f += c;
460 }
461
462 tmp = buf;
463 if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) )
464 {
465 j = 0;
466 while ( j < i && ( *tmp == '0' || *tmp == '.' ))
467 {
468 tmp++;
469 i--;
470 }
471 }
472 // else
473 // while (i < precision--)
474 // putc('0', f);
475 while (i-- > 0)
476 {
477 f += tmp[i];
478 }
479 while (size-- > 0)
480 {
481 f += ' ';
482 }
483 }
484 return true;
485 }
486
487 static bool
488 wnumberf(std::wstring& f, double __n, wchar_t exp_sign, int size, int precision, int type)
489 {
490 double exponent = 0.0;
491 double e;
492 long ie;
493
494 int i = 0;
495 int j = 0;
496
497 double frac, intr;
498 double p;
499 wchar_t *buf, *tmp, sign, c, ro = 0;
500 int result;
501
502 union
503 {
504 double* __n;
505 ieee_double_t* n;
506 } n;
507
508 n.__n = &__n;
509
510 if ( exp_sign == L'g' || exp_sign == L'G' || exp_sign == L'e' || exp_sign == L'E' ) {
511 ie = ((unsigned int)n.n->exponent - (unsigned int)0x3ff);
512 exponent = ie/3.321928;
513 }
514
515 if ( exp_sign == L'g' || exp_sign == L'G' )
516 {
517 type |= ZEROTRUNC;
518 if ( exponent < -4 || fabs(exponent) >= precision )
519 exp_sign -= 2; // g -> e and G -> E
520 else
521 exp_sign = L'f';
522 }
523
524 if ( exp_sign == L'e' || exp_sign == L'E' )
525 {
526 frac = modf(exponent,&e);
527 if ( frac > 0.5 )
528 e++;
529 else if ( frac < -0.5 )
530 e--;
531
532 result = wnumberf(f,__n/pow(10.0L,(long double) e),L'f',size-4, precision, type);
533 if (result < 0)
534 return false;
535 f += exp_sign;
536 size--;
537 ie = (long)e;
538 type = LEFT | PLUS;
539 if ( ie < 0 )
540 type |= SIGN;
541
542 result = wnumber(f,ie, 10,2, 2,type );
543 if (result < 0)
544 return false;
545 return true;
546 }
547
548 if ( exp_sign == L'f' )
549 {
550 buf = (wchar_t*)alloca(4096*sizeof(wchar_t));
551 if (type & LEFT)
552 type &= ~ZEROPAD;
553
554 c = (type & ZEROPAD) ? L'0' : L' ';
555 sign = 0;
556 if (type & SIGN)
557 {
558 if (__n < 0)
559 {
560 sign = L'-';
561 __n = fabs(__n);
562 size--;
563 }
564 else if (type & PLUS)
565 {
566 sign = L'+';
567 size--;
568 }
569 else if (type & SPACE)
570 {
571 sign = L' ';
572 size--;
573 }
574 }
575
576 frac = modf(__n,&intr);
577
578 // # flags forces a . and prevents trucation of trailing zero's
579
580 if ( precision > 0 ) {
581 //frac = modfl(__n,&intr);
582 i = precision-1;
583 while ( i >= 0 ) {
584 frac*=10.0L;
585 frac = modf(frac, &p);
586 buf[i] = (int)p + L'0';
587 i--;
588 }
589 i = precision;
590 size -= precision;
591
592 ro = 0;
593 if ( frac > 0.5 ) {
594 ro = 1;
595 }
596
597 if ( precision >= 1 || type & SPECIAL) {
598 buf[i++] = L'.';
599 size--;
600 }
601 }
602
603 if ( intr == 0.0 ) {
604 buf[i++] = L'0';
605 size--;
606 }
607 else {
608 while ( intr > 0.0 ) {
609 p = intr;
610 intr/=10.0L;
611 modf(intr, &intr);
612
613 p -= 10.0*intr;
614
615 buf[i++] = (int)p + L'0';
616 size--;
617 }
618 }
619
620 j = 0;
621 while ( j < i && ro == 1) {
622 if ( buf[j] >= L'0' && buf[j] <= L'8' ) {
623 buf[j]++;
624 ro = 0;
625 }
626 else if ( buf[j] == L'9' ) {
627 buf[j] = L'0';
628 }
629 j++;
630 }
631 if ( ro == 1 )
632 buf[i++] = L'1';
633
634 buf[i] = 0;
635
636 size -= precision;
637 if (!(type&(ZEROPAD+LEFT)))
638 {
639 while(size-->0)
640 f += L' ';
641 }
642 if (sign)
643 {
644 f += sign;
645 }
646
647 if (!(type&(ZEROPAD+LEFT)))
648 while(size-->0)
649 {
650 f += L' ';
651 }
652 if (type & SPECIAL) {
653 }
654
655 if (!(type & LEFT))
656 while (size-- > 0)
657 {
658 f += c;
659 }
660
661 tmp = buf;
662 if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) )
663 {
664 j = 0;
665 while ( j < i && ( *tmp == L'0' || *tmp == L'.' ))
666 {
667 tmp++;
668 i--;
669 }
670 }
671 while (i-- > 0)
672 {
673 f += tmp[i];
674 }
675 while (size-- > 0)
676 {
677 f += L' ';
678 }
679 }
680 return true;
681 }
682
683 static bool
684 numberfl(std::string& f, long double __n, char exp_sign, int size, int precision, int type)
685 {
686 long double exponent = 0.0;
687 long double e;
688 long ie;
689
690 //int x;
691 char *buf, *tmp;
692 int i = 0;
693 int j = 0;
694 //int k = 0;
695
696 long double frac, intr;
697 long double p;
698 char sign;
699 char c;
700 char ro = 0;
701
702 int result;
703
704 union
705 {
706 long double* __n;
707 ieee_long_double_t* n;
708 } n;
709
710 n.__n = &__n;
711
712 if ( exp_sign == 'g' || exp_sign == 'G' || exp_sign == 'e' || exp_sign == 'E' ) {
713 ie = ((unsigned int)n.n->exponent - (unsigned int)0x3fff);
714 exponent = ie/3.321928;
715 }
716
717 if ( exp_sign == 'g' || exp_sign == 'G' ) {
718 type |= ZEROTRUNC;
719 if ( exponent < -4 || fabs(exponent) >= precision )
720 exp_sign -= 2; // g -> e and G -> E
721 else
722 exp_sign = 'f';
723 }
724
725 if ( exp_sign == 'e' || exp_sign == 'E' ) {
726 frac = modfl(exponent,&e);
727 if ( frac > 0.5 )
728 e++;
729 else if ( frac < -0.5 )
730 e--;
731
732 result = numberf(f,__n/powl(10.0L,e),'f',size-4, precision, type);
733 if (result < 0)
734 return false;
735 f += exp_sign;
736 size--;
737 ie = (long)e;
738 type = LEFT | PLUS;
739 if ( ie < 0 )
740 type |= SIGN;
741
742 result = number(f,ie, 10,2, 2,type );
743 if (result < 0)
744 return false;
745 return true;
746 }
747
748 if ( exp_sign == 'f' )
749 {
750
751 buf = (char*)alloca(4096);
752 if (type & LEFT)
753 {
754 type &= ~ZEROPAD;
755 }
756
757 c = (type & ZEROPAD) ? '0' : ' ';
758 sign = 0;
759 if (type & SIGN)
760 {
761 if (__n < 0)
762 {
763 sign = '-';
764 __n = fabs(__n);
765 size--;
766 } else if (type & PLUS)
767 {
768 sign = '+';
769 size--;
770 } else if (type & SPACE)
771 {
772 sign = ' ';
773 size--;
774 }
775 }
776
777 frac = modfl(__n,&intr);
778
779 // # flags forces a . and prevents trucation of trailing zero's
780 if ( precision > 0 )
781 {
782 //frac = modfl(__n,&intr);
783
784 i = precision-1;
785 while ( i >= 0 )
786 {
787 frac*=10.0L;
788 frac = modfl((long double)frac, &p);
789 buf[i] = (int)p + '0';
790 i--;
791 }
792 i = precision;
793 size -= precision;
794
795 ro = 0;
796 if ( frac > 0.5 )
797 {
798 ro = 1;
799 }
800
801 if ( precision >= 1 || type & SPECIAL)
802 {
803 buf[i++] = '.';
804 size--;
805 }
806 }
807
808 if ( intr == 0.0 )
809 {
810 buf[i++] = '0';
811 size--;
812 }
813 else
814 {
815 while ( intr > 0.0 )
816 {
817 p=intr;
818 intr/=10.0L;
819 modfl(intr, &intr);
820
821 p -= 10.0L*intr;
822
823 buf[i++] = (int)p + '0';
824 size--;
825 }
826 }
827
828 j = 0;
829 while ( j < i && ro == 1) {
830 if ( buf[j] >= '0' && buf[j] <= '8' )
831 {
832 buf[j]++;
833 ro = 0;
834 }
835 else if ( buf[j] == '9' )
836 {
837 buf[j] = '0';
838 }
839 j++;
840 }
841 if ( ro == 1 )
842 buf[i++] = '1';
843
844 buf[i] = 0;
845
846 size -= precision;
847 if (!(type&(ZEROPAD+LEFT)))
848 {
849 while(size-->0)
850 f += ' ';
851 }
852 if (sign)
853 {
854 f += sign;
855 }
856
857 if (!(type&(ZEROPAD+LEFT)))
858 {
859 while(size-->0)
860 f += ' ';
861 }
862 if (type & SPECIAL) {
863 }
864
865 if (!(type & LEFT))
866 while (size-- > 0)
867 {
868 f += c;
869 }
870 tmp = buf;
871 if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) )
872 {
873 j = 0;
874 while ( j < i && ( *tmp == '0' || *tmp == '.' ))
875 {
876 tmp++;
877 i--;
878 }
879 }
880 while (i-- > 0)
881 {
882 f += tmp[i];
883 }
884 while (size-- > 0)
885 {
886 f += ' ';
887 }
888 }
889 return true;
890 }
891
892 static bool
893 wnumberfl(std::wstring& f, long double __n, wchar_t exp_sign, int size, int precision, int type)
894 {
895 long double exponent = 0.0;
896 long double e;
897 long ie;
898
899 wchar_t *buf, *tmp, sign, c, ro = 0;
900 int i = 0;
901 int j = 0;
902
903 long double frac, intr;
904 long double p;
905
906 int result;
907
908 union
909 {
910 long double* __n;
911 ieee_long_double_t* n;
912 } n;
913
914 n.__n = &__n;
915
916 if ( exp_sign == L'g' || exp_sign == L'G' || exp_sign == L'e' || exp_sign == L'E' ) {
917 ie = ((unsigned int)n.n->exponent - (unsigned int)0x3fff);
918 exponent = ie/3.321928;
919 }
920
921 if ( exp_sign == L'g' || exp_sign == L'G' ) {
922 type |= ZEROTRUNC;
923 if ( exponent < -4 || fabs(exponent) >= precision )
924 exp_sign -= 2; // g -> e and G -> E
925 else
926 exp_sign = 'f';
927 }
928
929 if ( exp_sign == L'e' || exp_sign == L'E' ) {
930 frac = modfl(exponent,&e);
931 if ( frac > 0.5 )
932 e++;
933 else if ( frac < -0.5 )
934 e--;
935
936 result = wnumberf(f,__n/powl(10.0L,e),L'f',size-4, precision, type);
937 if (result < 0)
938 return false;
939 f += exp_sign;
940 size--;
941 ie = (long)e;
942 type = LEFT | PLUS;
943 if ( ie < 0 )
944 type |= SIGN;
945
946 result = wnumber(f,ie, 10,2, 2,type );
947 if (result < 0)
948 return false;
949 return true;
950 }
951
952 if ( exp_sign == L'f' )
953 {
954
955 buf = (wchar_t*)alloca(4096*sizeof(wchar_t));
956 if (type & LEFT)
957 {
958 type &= ~ZEROPAD;
959 }
960
961 c = (type & ZEROPAD) ? L'0' : L' ';
962 sign = 0;
963 if (type & SIGN)
964 {
965 if (__n < 0)
966 {
967 sign = L'-';
968 __n = fabs(__n);
969 size--;
970 } else if (type & PLUS)
971 {
972 sign = L'+';
973 size--;
974 } else if (type & SPACE)
975 {
976 sign = L' ';
977 size--;
978 }
979 }
980
981 frac = modfl(__n,&intr);
982
983 // # flags forces a . and prevents trucation of trailing zero's
984 if ( precision > 0 )
985 {
986 //frac = modfl(__n,&intr);
987
988 i = precision-1;
989 while ( i >= 0 )
990 {
991 frac*=10.0L;
992 frac = modfl((long double)frac, &p);
993 buf[i] = (int)p + L'0';
994 i--;
995 }
996 i = precision;
997 size -= precision;
998
999 ro = 0;
1000 if ( frac > 0.5 )
1001 {
1002 ro = 1;
1003 }
1004
1005 if ( precision >= 1 || type & SPECIAL)
1006 {
1007 buf[i++] = L'.';
1008 size--;
1009 }
1010 }
1011
1012 if ( intr == 0.0 )
1013 {
1014 buf[i++] = L'0';
1015 size--;
1016 }
1017 else
1018 {
1019 while ( intr > 0.0 )
1020 {
1021 p=intr;
1022 intr/=10.0L;
1023 modfl(intr, &intr);
1024
1025 p -= 10.0L*intr;
1026
1027 buf[i++] = (int)p + L'0';
1028 size--;
1029 }
1030 }
1031
1032 j = 0;
1033 while ( j < i && ro == 1) {
1034 if ( buf[j] >= L'0' && buf[j] <= L'8' )
1035 {
1036 buf[j]++;
1037 ro = 0;
1038 }
1039 else if ( buf[j] == L'9' )
1040 {
1041 buf[j] = L'0';
1042 }
1043 j++;
1044 }
1045 if ( ro == 1 )
1046 buf[i++] = L'1';
1047
1048 buf[i] = 0;
1049
1050 size -= precision;
1051 if (!(type&(ZEROPAD+LEFT)))
1052 {
1053 while(size-->0)
1054 f += L' ';
1055 }
1056 if (sign)
1057 {
1058 f += sign;
1059 }
1060
1061 if (!(type&(ZEROPAD+LEFT)))
1062 {
1063 while(size-->0)
1064 f += L' ';
1065 }
1066 if (type & SPECIAL) {
1067 }
1068
1069 if (!(type & LEFT))
1070 while (size-- > 0)
1071 {
1072 f += c;
1073 }
1074 tmp = buf;
1075 if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) )
1076 {
1077 j = 0;
1078 while ( j < i && ( *tmp == L'0' || *tmp == L'.' ))
1079 {
1080 tmp++;
1081 i--;
1082 }
1083 }
1084 while (i-- > 0)
1085 {
1086 f += tmp[i];
1087 }
1088 while (size-- > 0)
1089 {
1090 f += L' ';
1091 }
1092 }
1093 return true;
1094 }
1095
1096 static int
1097 do_string(std::string& f, const char* s, int len, int field_width, int precision, int flags)
1098 {
1099 int i, done = 0;
1100 if (s == NULL)
1101 {
1102 s = "<NULL>";
1103 len = 6;
1104 }
1105 else
1106 {
1107 if (len == -1)
1108 {
1109 len = 0;
1110 while ((unsigned int)len < (unsigned int)precision && s[len])
1111 len++;
1112 }
1113 else
1114 {
1115 if ((unsigned int)len > (unsigned int)precision)
1116 len = precision;
1117 }
1118 }
1119 if (!(flags & LEFT))
1120 while (len < field_width--)
1121 {
1122 f += ' ';
1123 done++;
1124 }
1125 for (i = 0; i < len; ++i)
1126 {
1127 f += *s++;
1128 done++;
1129 }
1130 while (len < field_width--)
1131 {
1132 f += ' ';
1133 done++;
1134 }
1135 return done;
1136 }
1137
1138 static int
1139 do_wstring(std::wstring& f, const wchar_t* s, int len, int field_width, int precision, int flags)
1140 {
1141 int i, done = 0;
1142 if (s == NULL)
1143 {
1144 s = L"<NULL>";
1145 len = 6;
1146 }
1147 else
1148 {
1149 if (len == -1)
1150 {
1151 len = 0;
1152 while ((unsigned int)len < (unsigned int)precision && s[len])
1153 len++;
1154 }
1155 else
1156 {
1157 if ((unsigned int)len > (unsigned int)precision)
1158 len = precision;
1159 }
1160 }
1161 if (!(flags & LEFT))
1162 while (len < field_width--)
1163 {
1164 f += L' ';
1165 done++;
1166 }
1167 for (i = 0; i < len; ++i)
1168 {
1169 f += *s++;
1170 done++;
1171 }
1172 while (len < field_width--)
1173 {
1174 f += L' ';
1175 done++;
1176 }
1177 return done;
1178 }
1179
1180 static int
1181 stringw(std::string& f, const wchar_t* sw, int len, int field_width, int precision, int flags)
1182 {
1183 int i, done = 0;
1184 if (sw == NULL)
1185 {
1186 sw = L"<NULL>";
1187 len = 6;
1188 }
1189 else
1190 {
1191 if (len == -1)
1192 {
1193 len = 0;
1194 while ((unsigned int)len < (unsigned int)precision && sw[len])
1195 len++;
1196 }
1197 else
1198 {
1199 if ((unsigned int)len > (unsigned int)precision)
1200 len = precision;
1201 }
1202 }
1203 if (!(flags & LEFT))
1204 while (len < field_width--)
1205 {
1206 f += ' ';
1207 done++;
1208 }
1209 for (i = 0; i < len; ++i)
1210 {
1211 #define MY_MB_CUR_MAX 1
1212 char mb[MY_MB_CUR_MAX];
1213 int mbcount, j;
1214 mbcount = wctomb(mb, *sw++);
1215 if (mbcount <= 0)
1216 {
1217 break;
1218 }
1219 for (j = 0; j < mbcount; j++)
1220 {
1221 f += mb[j];
1222 done++;
1223 }
1224 }
1225 while (len < field_width--)
1226 {
1227 f += ' ';
1228 done++;
1229 }
1230 return done;
1231 }
1232
1233 static int
1234 wstringa(std::wstring& f, const char* sa, int len, int field_width, int precision, int flags)
1235 {
1236 int i, done = 0;
1237 if (sa == NULL)
1238 {
1239 sa = "<NULL>";
1240 len = 6;
1241 }
1242 else
1243 {
1244 if (len == -1)
1245 {
1246 len = 0;
1247 while ((unsigned int)len < (unsigned int)precision && sa[len])
1248 len++;
1249 }
1250 else
1251 {
1252 if ((unsigned int)len > (unsigned int)precision)
1253 len = precision;
1254 }
1255 }
1256 if (!(flags & LEFT))
1257 while (len < field_width--)
1258 {
1259 f += L' ';
1260 done++;
1261 }
1262 for (i = 0; i < len;)
1263 {
1264 wchar_t w;
1265 int mbcount;
1266 mbcount = mbtowc(&w, sa, len-i);
1267 if (mbcount <= 0)
1268 break;
1269 f += w;
1270 done++;
1271 i += mbcount;
1272 }
1273 while (len < field_width--)
1274 {
1275 f += L' ';
1276 done++;
1277 }
1278 return done;
1279 }
1280
1281 #define _isnanl _isnan
1282 #define _finitel _finite
1283
1284 std::string
1285 ssvprintf ( const char *fmt, va_list args )
1286 {
1287 ULONGLONG num;
1288 int base;
1289 long double _ldouble;
1290 double _double;
1291 const char *s;
1292 const wchar_t* sw;
1293 int result;
1294 std::string f;
1295
1296 int flags; /* flags to number() */
1297
1298 int field_width; /* width of output field */
1299 int precision; /* min. # of digits for integers; max
1300 number of chars for from string */
1301 int qualifier = 0; /* 'h', 'l', 'L' or 'I64' for integer fields */
1302
1303 for (; *fmt ; ++fmt)
1304 {
1305 if (*fmt != '%')
1306 {
1307 f += *fmt;
1308 continue;
1309 }
1310
1311 /* process flags */
1312 flags = 0;
1313 repeat:
1314 ++fmt; /* this also skips first '%' */
1315 switch (*fmt) {
1316 case '-': flags |= LEFT; goto repeat;
1317 case '+': flags |= PLUS; goto repeat;
1318 case ' ': flags |= SPACE; goto repeat;
1319 case '#': flags |= SPECIAL; goto repeat;
1320 case '0': flags |= ZEROPAD; goto repeat;
1321 }
1322
1323 /* get field width */
1324 field_width = -1;
1325 if (isdigit(*fmt))
1326 field_width = skip_atoi(&fmt);
1327 else if (*fmt == '*') {
1328 ++fmt;
1329 /* it's the next argument */
1330 field_width = va_arg(args, int);
1331 if (field_width < 0) {
1332 field_width = -field_width;
1333 flags |= LEFT;
1334 }
1335 }
1336
1337 /* get the precision */
1338 precision = -1;
1339 if (*fmt == '.') {
1340 ++fmt;
1341 if (isdigit(*fmt))
1342 precision = skip_atoi(&fmt);
1343 else if (*fmt == '*') {
1344 ++fmt;
1345 /* it's the next argument */
1346 precision = va_arg(args, int);
1347 }
1348 if (precision < 0)
1349 precision = 0;
1350 }
1351
1352 /* get the conversion qualifier */
1353 qualifier = 0;
1354 // %Z can be just stand alone or as size_t qualifier
1355 if ( *fmt == 'Z' ) {
1356 qualifier = *fmt;
1357 switch ( *(fmt+1)) {
1358 case 'o':
1359 case 'b':
1360 case 'X':
1361 case 'x':
1362 case 'd':
1363 case 'i':
1364 case 'u':
1365 ++fmt;
1366 break;
1367 default:
1368 break;
1369 }
1370 } else if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'w') {
1371 qualifier = *fmt;
1372 ++fmt;
1373 } else if (*fmt == 'I' && *(fmt+1) == '6' && *(fmt+2) == '4') {
1374 qualifier = *fmt;
1375 fmt += 3;
1376 }
1377
1378 // go fine with ll instead of L
1379 if ( *fmt == 'l' ) {
1380 ++fmt;
1381 qualifier = 'L';
1382 }
1383
1384 /* default base */
1385 base = 10;
1386
1387 switch (*fmt) {
1388 case 'c':
1389 if (!(flags & LEFT))
1390 while (--field_width > 0)
1391 {
1392 f += ' ';
1393 }
1394 if (qualifier == 'l' || qualifier == 'w')
1395 {
1396 f += (char)(unsigned char)(wchar_t) va_arg(args,int);
1397 }
1398 else
1399 {
1400 f += (char)(unsigned char) va_arg(args,int);
1401 }
1402 while (--field_width > 0)
1403 {
1404 f += ' ';
1405 }
1406 continue;
1407
1408 case 'C':
1409 if (!(flags & LEFT))
1410 while (--field_width > 0)
1411 {
1412 f += ' ';
1413 }
1414 if (qualifier == 'h')
1415 {
1416 f += (char)(unsigned char) va_arg(args,int);
1417 }
1418 else
1419 {
1420 f += (char)(unsigned char)(wchar_t) va_arg(args,int);
1421 }
1422 while (--field_width > 0)
1423 {
1424 f += ' ';
1425 }
1426 continue;
1427
1428 case 's':
1429 if (qualifier == 'l' || qualifier == 'w') {
1430 /* print unicode string */
1431 sw = va_arg(args, wchar_t *);
1432 result = stringw(f, sw, -1, field_width, precision, flags);
1433 } else {
1434 /* print ascii string */
1435 s = va_arg(args, char *);
1436 result = do_string(f, s, -1, field_width, precision, flags);
1437 }
1438 if (result < 0)
1439 {
1440 assert(!"TODO FIXME handle error better");
1441 return f;
1442 }
1443 continue;
1444
1445 case 'S':
1446 if (qualifier == 'h') {
1447 /* print ascii string */
1448 s = va_arg(args, char *);
1449 result = do_string(f, s, -1, field_width, precision, flags);
1450 } else {
1451 /* print unicode string */
1452 sw = va_arg(args, wchar_t *);
1453 result = stringw(f, sw, -1, field_width, precision, flags);
1454 }
1455 if (result < 0)
1456 {
1457 assert(!"TODO FIXME handle error better");
1458 return f;
1459 }
1460 continue;
1461
1462 /*case 'Z':
1463 if (qualifier == 'w') {
1464 // print counted unicode string
1465 PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING);
1466 if ((pus == NULL) || (pus->Buffer == NULL)) {
1467 sw = NULL;
1468 len = -1;
1469 } else {
1470 sw = pus->Buffer;
1471 len = pus->Length / sizeof(WCHAR);
1472 }
1473 result = stringw(f, sw, len, field_width, precision, flags);
1474 } else {
1475 // print counted ascii string
1476 PANSI_STRING pas = va_arg(args, PANSI_STRING);
1477 if ((pas == NULL) || (pas->Buffer == NULL)) {
1478 s = NULL;
1479 len = -1;
1480 } else {
1481 s = pas->Buffer;
1482 len = pas->Length;
1483 }
1484 result = string(f, s, -1, field_width, precision, flags);
1485 }
1486 if (result < 0)
1487 return -1;
1488 continue;*/
1489
1490 case 'e':
1491 case 'E':
1492 case 'f':
1493 case 'g':
1494 case 'G':
1495 if (qualifier == 'l' || qualifier == 'L' ) {
1496 _ldouble = va_arg(args, long double);
1497
1498 if ( _isnanl(_ldouble) )
1499 {
1500 f += "Nan";
1501 }
1502 else if ( !_finitel(_ldouble) )
1503 {
1504 if ( _ldouble < 0 )
1505 f += "-Inf";
1506 else
1507 f += "+Inf";
1508 } else {
1509 if ( precision == -1 )
1510 precision = 6;
1511 result = numberfl(f,_ldouble,*fmt,field_width,precision,flags);
1512 if (result < 0)
1513 {
1514 assert(!"TODO FIXME handle error better");
1515 return f;
1516 }
1517 }
1518 } else {
1519 _double = (double)va_arg(args, double);
1520
1521 if ( _isnan(_double) )
1522 {
1523 f += "Nan";
1524 }
1525 else if ( !_finite(_double) )
1526 {
1527 if ( _double < 0 )
1528 f += "-Inf";
1529 else
1530 f += "+Inf";
1531 }
1532 else
1533 {
1534 if ( precision == -1 )
1535 precision = 6;
1536 result = numberf(f,_double,*fmt,field_width,precision,flags);
1537 if (result < 0)
1538 {
1539 assert(!"TODO FIXME handle error better");
1540 return f;
1541 }
1542 }
1543 }
1544 continue;
1545
1546 case 'p':
1547 if (field_width == -1) {
1548 field_width = 2*sizeof(void *);
1549 flags |= ZEROPAD;
1550 }
1551 result = number(f,
1552 (unsigned long) va_arg(args, void *), 16,
1553 field_width, precision, flags);
1554 if (result < 0)
1555 {
1556 assert(!"TODO FIXME handle error better");
1557 return f;
1558 }
1559 continue;
1560
1561 case 'n':
1562 if (qualifier == 'l') {
1563 long * ip = va_arg(args, long *);
1564 *ip = 0;
1565 } else {
1566 int * ip = va_arg(args, int *);
1567 *ip = 0;
1568 }
1569 continue;
1570
1571 /* integer number formats - set up the flags and "break" */
1572 case 'o':
1573 base = 8;
1574 break;
1575
1576 case 'b':
1577 base = 2;
1578 break;
1579
1580 case 'X':
1581 flags |= LARGE;
1582 case 'x':
1583 base = 16;
1584 break;
1585
1586 case 'd':
1587 case 'i':
1588 flags |= SIGN;
1589 case 'u':
1590 break;
1591
1592 default:
1593 if (*fmt != '%')
1594 {
1595 f += '%';
1596 }
1597 if (*fmt)
1598 {
1599 f += *fmt;
1600 }
1601 else
1602 --fmt;
1603 continue;
1604 }
1605
1606 if (qualifier == 'I')
1607 num = va_arg(args, ULONGLONG);
1608 else if (qualifier == 'l') {
1609 if (flags & SIGN)
1610 num = va_arg(args, long);
1611 else
1612 num = va_arg(args, unsigned long);
1613 }
1614 else if (qualifier == 'h') {
1615 if (flags & SIGN)
1616 num = va_arg(args, int);
1617 else
1618 num = va_arg(args, unsigned int);
1619 }
1620 else if (flags & SIGN)
1621 num = va_arg(args, int);
1622 else
1623 num = va_arg(args, unsigned int);
1624 result = number(f, num, base, field_width, precision, flags);
1625 if (result < 0)
1626 {
1627 assert(!"TODO FIXME handle error better");
1628 return f;
1629 }
1630 }
1631 //putc('\0',f);
1632 return f;
1633 }
1634
1635 std::wstring
1636 sswvprintf ( const wchar_t* fmt, va_list args )
1637 {
1638 ULONGLONG num;
1639 int base;
1640 long double _ldouble;
1641 double _double;
1642 const wchar_t* s;
1643 const char* sa;
1644 int result;
1645 std::wstring f;
1646
1647 int flags; /* flags to number() */
1648
1649 int field_width; /* width of output field */
1650 int precision; /* min. # of digits for integers; max
1651 number of chars for from string */
1652 int qualifier = 0; /* 'h', 'l', 'L' or 'I64' for integer fields */
1653
1654 for (; *fmt ; ++fmt)
1655 {
1656 if (*fmt != L'%')
1657 {
1658 f += *fmt;
1659 continue;
1660 }
1661
1662 /* process flags */
1663 flags = 0;
1664 repeat:
1665 ++fmt; /* this also skips first '%' */
1666 switch (*fmt) {
1667 case L'-': flags |= LEFT; goto repeat;
1668 case L'+': flags |= PLUS; goto repeat;
1669 case L' ': flags |= SPACE; goto repeat;
1670 case L'#': flags |= SPECIAL; goto repeat;
1671 case L'0': flags |= ZEROPAD; goto repeat;
1672 }
1673
1674 /* get field width */
1675 field_width = -1;
1676 if (isdigit(*fmt))
1677 field_width = skip_wtoi(&fmt);
1678 else if (*fmt == L'*') {
1679 ++fmt;
1680 /* it's the next argument */
1681 field_width = va_arg(args, int);
1682 if (field_width < 0) {
1683 field_width = -field_width;
1684 flags |= LEFT;
1685 }
1686 }
1687
1688 /* get the precision */
1689 precision = -1;
1690 if (*fmt == L'.') {
1691 ++fmt;
1692 if (iswdigit(*fmt))
1693 precision = skip_wtoi(&fmt);
1694 else if (*fmt == L'*') {
1695 ++fmt;
1696 /* it's the next argument */
1697 precision = va_arg(args, int);
1698 }
1699 if (precision < 0)
1700 precision = 0;
1701 }
1702
1703 /* get the conversion qualifier */
1704 qualifier = 0;
1705 // %Z can be just stand alone or as size_t qualifier
1706 if ( *fmt == L'Z' ) {
1707 qualifier = *fmt;
1708 switch ( *(fmt+1)) {
1709 case L'o':
1710 case L'b':
1711 case L'X':
1712 case L'x':
1713 case L'd':
1714 case L'i':
1715 case L'u':
1716 ++fmt;
1717 break;
1718 default:
1719 break;
1720 }
1721 } else if (*fmt == L'h' || *fmt == L'l' || *fmt == L'L' || *fmt == L'w') {
1722 qualifier = *fmt;
1723 ++fmt;
1724 } else if (*fmt == L'I' && *(fmt+1) == L'6' && *(fmt+2) == L'4') {
1725 qualifier = *fmt;
1726 fmt += 3;
1727 }
1728
1729 // go fine with ll instead of L
1730 if ( *fmt == L'l' ) {
1731 ++fmt;
1732 qualifier = L'L';
1733 }
1734
1735 /* default base */
1736 base = 10;
1737
1738 switch (*fmt) {
1739 case L'c':
1740 if (!(flags & LEFT))
1741 while (--field_width > 0)
1742 {
1743 f += L' ';
1744 }
1745 if ( qualifier == L'h' )
1746 {
1747 f += (wchar_t)(char)(unsigned char) va_arg(args,int);
1748 }
1749 else
1750 {
1751 f += (wchar_t) va_arg(args,int);
1752 }
1753 while (--field_width > 0)
1754 {
1755 f += ' ';
1756 }
1757 continue;
1758
1759 case 'C':
1760 if (!(flags & LEFT))
1761 while (--field_width > 0)
1762 {
1763 f += L' ';
1764 }
1765 if (qualifier == L'l' || qualifier == L'w')
1766 {
1767 f += (wchar_t) va_arg(args,int);
1768 }
1769 else
1770 {
1771 f += (wchar_t)(char)(unsigned char) va_arg(args,int);
1772 }
1773 while (--field_width > 0)
1774 {
1775 f += L' ';
1776 }
1777 continue;
1778
1779 case 's':
1780 if (qualifier == L'h') {
1781 /* print ascii string */
1782 sa = va_arg(args, char *);
1783 result = wstringa(f, sa, -1, field_width, precision, flags);
1784 } else {
1785 /* print unicode string */
1786 s = va_arg(args, wchar_t *);
1787 result = do_wstring(f, s, -1, field_width, precision, flags);
1788 }
1789 if (result < 0)
1790 {
1791 assert(!"TODO FIXME handle error better");
1792 return f;
1793 }
1794 continue;
1795
1796 case 'S':
1797 if (qualifier == L'l' || qualifier == L'w') {
1798 /* print unicode string */
1799 s = va_arg(args, wchar_t *);
1800 result = do_wstring(f, s, -1, field_width, precision, flags);
1801 } else {
1802 /* print ascii string */
1803 sa = va_arg(args, char *);
1804 result = wstringa(f, sa, -1, field_width, precision, flags);
1805 }
1806 if (result < 0)
1807 {
1808 assert(!"TODO FIXME handle error better");
1809 return f;
1810 }
1811 continue;
1812
1813 case L'e':
1814 case L'E':
1815 case L'f':
1816 case L'g':
1817 case L'G':
1818 if (qualifier == L'l' || qualifier == L'L' )
1819 {
1820 _ldouble = va_arg(args, long double);
1821
1822 if ( _isnanl(_ldouble) )
1823 {
1824 f += L"Nan";
1825 }
1826 else if ( !_finitel(_ldouble) )
1827 {
1828 if ( _ldouble < 0 )
1829 f += L"-Inf";
1830 else
1831 f += L"+Inf";
1832 } else {
1833 if ( precision == -1 )
1834 precision = 6;
1835 result = wnumberfl(f,_ldouble,*fmt,field_width,precision,flags);
1836 if (result < 0)
1837 {
1838 assert(!"TODO FIXME handle error better");
1839 return f;
1840 }
1841 }
1842 } else {
1843 _double = (double)va_arg(args, double);
1844
1845 if ( _isnan(_double) )
1846 {
1847 f += L"Nan";
1848 }
1849 else if ( !_finite(_double) )
1850 {
1851 if ( _double < 0 )
1852 f += L"-Inf";
1853 else
1854 f += L"+Inf";
1855 }
1856 else
1857 {
1858 if ( precision == -1 )
1859 precision = 6;
1860 result = wnumberf(f,_double,*fmt,field_width,precision,flags);
1861 if (result < 0)
1862 {
1863 assert(!"TODO FIXME handle error better");
1864 return f;
1865 }
1866 }
1867 }
1868 continue;
1869
1870 case L'p':
1871 if (field_width == -1) {
1872 field_width = 2*sizeof(void *);
1873 flags |= ZEROPAD;
1874 }
1875 result = wnumber(f,
1876 (unsigned long) va_arg(args, void *), 16,
1877 field_width, precision, flags);
1878 if (result < 0)
1879 {
1880 assert(!"TODO FIXME handle error better");
1881 return f;
1882 }
1883 continue;
1884
1885 case L'n':
1886 if (qualifier == L'l') {
1887 long * ip = va_arg(args, long *);
1888 *ip = 0;
1889 } else {
1890 int * ip = va_arg(args, int *);
1891 *ip = 0;
1892 }
1893 continue;
1894
1895 /* integer number formats - set up the flags and "break" */
1896 case L'o':
1897 base = 8;
1898 break;
1899
1900 case L'b':
1901 base = 2;
1902 break;
1903
1904 case L'X':
1905 flags |= LARGE;
1906 case L'x':
1907 base = 16;
1908 break;
1909
1910 case L'd':
1911 case L'i':
1912 flags |= SIGN;
1913 case L'u':
1914 break;
1915
1916 default:
1917 if (*fmt != L'%')
1918 {
1919 f += L'%';
1920 }
1921 if (*fmt)
1922 {
1923 f += *fmt;
1924 }
1925 else
1926 --fmt;
1927 continue;
1928 }
1929
1930 if (qualifier == L'I')
1931 num = va_arg(args, ULONGLONG);
1932 else if (qualifier == L'l') {
1933 if (flags & SIGN)
1934 num = va_arg(args, long);
1935 else
1936 num = va_arg(args, unsigned long);
1937 }
1938 else if (qualifier == L'h') {
1939 if (flags & SIGN)
1940 num = va_arg(args, int);
1941 else
1942 num = va_arg(args, unsigned int);
1943 }
1944 else if (flags & SIGN)
1945 num = va_arg(args, int);
1946 else
1947 num = va_arg(args, unsigned int);
1948 result = wnumber(f, num, base, field_width, precision, flags);
1949 if (result < 0)
1950 {
1951 assert(!"TODO FIXME handle error better");
1952 return f;
1953 }
1954 }
1955 //putc('\0',f);
1956 return f;
1957 }