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