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