1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859
|
// $Header$
//
// Copyright (C) 2002 - 2007, by
//
// Carlo Wood, Run on IRC <carlo@alinoe.com>
// RSA-1024 0x624ACAD5 1997-01-26 Sign & Encrypt
// Fingerprint16 = 32 EC A7 B6 AC DB 65 A6 F6 F6 55 DD 1C DC FF 61
//
// This file may be distributed under the terms of the Q Public License
// version 1.0 as appearing in the file LICENSE.QPL included in the
// packaging of this file.
//
/*!
\addtogroup group_demangle demangle_type() and demangle_symbol()
\ingroup group_type_info
Libcwd comes with its own demangler functions.
demangle_type() writes the \em mangled type name \p input
to the string \p output; \p input should be the mangled name
as returned by <CODE>typeid(OBJECT).name()</CODE> (using gcc-2.95.1 or higher).
demangle_symbol() writes the \em mangled symbol name \p input
to the string \p output; \p input should be the mangled name
as returned by <CODE>elfxx::asymbol_st::name</CODE>
which is what is returned by
\ref libcwd::location_ct::mangled_function_name "location_ct::mangled_function_name()"
and pc_mangled_function_name().
The direct use of these functions should be avoided, instead use the function type_info_of().
*/
//
// This file has been tested with gcc-3.x
//
// The description of how the mangling is done in the new ABI was found on
// http://www.codesourcery.com/cxx-abi/abi.html#mangling revision 1.74.
//
// To compile a standalone demangler:
// g++ -g -DSTANDALONE -DCWDEBUG -Iinclude demangle3.cc -Wl,--rpath,`pwd`/.libs -L.libs -lcwd -o c++filt
//
#include "sys.h"
#include "cwd_debug.h"
#include <libcwd/demangle.h>
#include <libcwd/private_assert.h>
#include <limits>
#ifdef STANDALONE
#ifdef CWDEBUG
namespace libcwd {
namespace channels {
namespace dc {
channel_ct demangler("DEMANGLER");
} // namespace dc
} // namespace channels
} // namespace libcwd
#endif
#define _GLIBCXX_DEMANGLER_DEBUG(x) __Debug(x)
#define _GLIBCXX_DEMANGLER_DOUT(cntrl, data) __Dout(cntrl, data)
#define _GLIBCXX_DEMANGLER_DOUT_ENTERING(x) \
__Dout(dc::demangler|continued_cf|flush_cf, "Entering " << x << "(\"" << &M_str[M_pos] << "\", \"" << output << "\") ")
#define _GLIBCXX_DEMANGLER_RETURN \
do { \
if (M_result) \
__Dout(dc::finish, '[' << M_pos << "; \"" << output << "\"]" ); \
else \
__Dout(dc::finish, "(failed)"); return M_result; \
} while(0)
#define _GLIBCXX_DEMANGLER_FAILURE \
do { \
if (M_result) \
{ \
M_result = false; \
__Dout(dc::finish, "[failure]"); \
} \
else \
__Dout(dc::finish, "(failed)"); \
return false; \
} while(0)
#define _GLIBCXX_DEMANGLER_DOUT_ENTERING2(x) \
do { \
__Dout(dc::demangler|continued_cf|flush_cf, "Entering " << x); \
if (qualifiers) \
__Dout(dc::continued, " [with qualifiers: " << *qualifiers << ']'); \
__Dout(dc::continued, "(\"" << &M_str[M_pos] << "\", \"" << prefix << "\", \"" << postfix << "\") "); \
} while(0)
#define _GLIBCXX_DEMANGLER_RETURN2 \
do { \
if (M_result) \
__Dout(dc::finish, '[' << M_pos << "; \"" << prefix << "\", \"" << postfix << "\"]" ); \
else \
__Dout(dc::finish, "(failed)"); \
return M_result; \
} while(0)
#define _GLIBCXX_DEMANGLER_DOUT_ENTERING3(x) \
do { \
__Dout(dc::demangler|continued_cf|flush_cf, "Entering " << x); \
__Dout(dc::continued, " [with qualifier list: " << *this << ']'); \
__Dout(dc::continued, " (\"" << prefix << "\", \"" << postfix << "\") "); \
} while(0)
#define _GLIBCXX_DEMANGLER_RETURN3 \
do { \
__Dout(dc::finish, "[\"" << prefix << "\", \"" << postfix << "\"]" ); \
return; \
} while(0)
#endif // STANDALONE
#include <demangle.h> // The actual demangler code.
namespace
{
// class decimal_float
//
// This internal class represents a floating point value
// with a precision of `mantissa_size_c' * 4 digits.
// With `mantissa_size_c' set to 5 that gives 20 digits,
// being more than 66 bits. However, due to round off
// errors, the last `size of binary exponent' bits are
// unreliable.
//
// For IEEE double precision, the size of the exponent
// is 11 bits and thus is this class only accurate in
// 55 bits. Therefore, only 17 digits may be printed
// in that case. This size is precisely significant for
// the 52 bits of precision in the IEEE format as well.
//
// For IEEE single precision, the size of the exponent
// is 8 bits and we will have 58 bits of precision. It
// makes no sense to print more than 7 digits in that
// case because IEEE single precision has only 23 bits
// of precision by itself.
//
// The internal value of a `decimal_float' object is
//
// ( mantissa[0] +
// 10000 * mantissa[1] +
// 10000**2 * mantissa[2] +
// 10000**3 * mantissa[3] +
// 10000**4 * mantissa[4] ) * 10**exponent
//
// The member `max_precision_reached' is set to true
// when the value of the object cannot be multiplied
// with 10 anymore without changing the exponent,
// in other words, when mantissa[4] >= 1000.
// Its value is fuzzy however and only influences
// the maximum achievable accuracy.
static int const mantissa_size_c = 5;
struct decimal_float_data {
unsigned long mantissa[mantissa_size_c];
int exponent;
bool max_precision_reached;
};
class decimal_float {
private:
decimal_float_data M_data;
private:
void M_do_overflow(unsigned long prev_borrow);
void M_do_carry(void);
public:
void set_2pow2pow(int power);
void set_2pow(int power);
void set_expstart(int expsize);
void set_zero(void);
void divide_by_two(bool decrement_exponent);
bool decrement_exponent(void);
decimal_float& operator+=(decimal_float const& term);
decimal_float& operator*=(decimal_float const& factor);
void print_to_with_precision(char* buf, int precision) const;
};
// These names must match the corresponding index of the table below
// and the p* constants must be contigious and in the given order.
// Same for the constants m1023 ... m15.
// Name Table-index
int const m1023 = 0; // Corresponds with an exponent of 11 bits.
#if 0
int const m511 = 1;
int const m255 = 2;
int const m127 = 3; // Corresponds with an exponent of 8 bits.
int const m63 = 4;
int const m31 = 5;
int const m15 = 6;
#endif
int const m1 = 7;
int const m0 = 8; // Must have the same exponent as m1.
int const p1 = 9;
#if 0
int const p2 = 10;
int const p4 = 11;
int const p8 = 12;
int const p16 = 13;
int const p32 = 14;
int const p64 = 15;
int const p128 = 16;
int const p256 = 17;
int const p512 = 18;
int const p1024 = 19;
#endif
decimal_float_data const constants[] = {
{ { 6915, 3600, 2925, 5369, 1112 }, -327, true }, // m1023; 2 ** -1023
{ { 3487, 41, 4624, 6681, 1491 }, -173, true }, // m511; 2 ** -511
{ { 9251, 8888, 1101, 2337, 1727 }, -96, true }, // m255; 2 ** -255
{ { 5398, 1437, 5411, 4717, 5877 }, -58, true }, // m127; 2 ** -127
{ { 4340, 5504, 7248, 2021, 1084 }, -38, true }, // m63; 2 ** -63
{ { 5781, 7392, 7307, 6128, 4656 }, -29, true }, // m31; 2 ** -31
{ { 0, 0, 1250, 7578, 3051 }, -24, true }, // m15; 2 ** -15
{ { 5, 0, 0, 0, 0 }, -1, false }, // m1; 2 ** -1
{ { 10, 0, 0, 0, 0 }, -1, false }, // m0; 2 ** 0
{ { 2, 0, 0, 0, 0 }, 0, false }, // p1; 2 ** 1
{ { 4, 0, 0, 0, 0 }, 0, false }, // p2; 2 ** 2
{ { 16, 0, 0, 0, 0 }, 0, false }, // p4; 2 ** 4
{ { 256, 0, 0, 0, 0 }, 0, false }, // p8; 2 ** 8
{ { 5536, 6, 0, 0, 0 }, 0, false }, // p16; 2 ** 16
{ { 7296, 9496, 42, 0, 0 }, 0, false }, // p32; 2 ** 32
{ { 1616, 955, 737, 6744, 1844 }, 0, true }, // p64; 2 ** 64
{ { 6346, 9384, 6920, 8236, 3402 }, 19, true }, // p128; 2 ** 128
{ { 9542, 3161, 9237, 9208, 1157 }, 58, true }, // p256; 2 ** 256
{ { 7100, 4259, 9299, 7807, 1340 }, 135, true }, // p512; 2 ** 512
{ { 9077, 2315, 3486, 6931, 1797 }, 289, true } // p1024; 2 ** 1024
};
// Handle excess digits in the most significant
// element of the mantissa array.
void decimal_float::M_do_overflow(unsigned long prev_borrow)
{
// assert(M_data.mantissa[mantissa_size_c - 1] > 9999);
// Even after shifting the excess digits right,
// M_data.mantissa[mantissa_size_c - 1] will still be
// larger than 999.
M_data.max_precision_reached = true;
// Count the excess digits and update the exponent
// already in order to keep the value constant.
unsigned long divider = 10;
++M_data.exponent;
while (prev_borrow >= divider)
{
divider *= 10;
++M_data.exponent;
}
// Finally, shift the value in the mantissa a few
// digits to the right. Round off what falls off.
unsigned long multiplier = 10000 / divider;
for (int i = mantissa_size_c - 1; i >= 0; --i)
{
unsigned long borrow = M_data.mantissa[i] % divider;
if (i == 0)
M_data.mantissa[i] += divider / 2; // Round off.
M_data.mantissa[i] /= divider;
M_data.mantissa[i] += prev_borrow * multiplier;
prev_borrow = borrow;
}
}
// Handle excess digits in the elements of the mantissa array.
void decimal_float::M_do_carry(void)
{
for (int i = 0; i < mantissa_size_c - 1; ++i)
{
if (M_data.mantissa[i] >= 10000)
{
M_data.mantissa[i + 1] += M_data.mantissa[i] / 10000;
M_data.mantissa[i] %= 10000;
}
}
if (M_data.mantissa[mantissa_size_c - 1] >= 10000)
M_do_overflow(0);
}
// Initialize the object to a value of 2 ** (2 ** power).
inline void decimal_float::set_2pow2pow(int power)
{
// assert(0 <= power && power <= 10);
std::memcpy(&M_data, &constants[p1 + power], sizeof(decimal_float_data));
}
// Initialize the object to a value of 2 ** power.
inline void decimal_float::set_2pow(int power)
{
// assert(power == 0 || power == 1);
std::memcpy(&M_data, &constants[power], sizeof(decimal_float_data));
}
// Initialize the object to a value of 2 ** (1 - (2 ** (expsize - 1))).
inline void decimal_float::set_expstart(int expsize)
{
// assert(expsize <= 11 && expsize >= 5);
std::memcpy(&M_data, &constants[m1023 + 11 - expsize],
sizeof(decimal_float_data));
}
// Initialize the object to zero. Must have the same exponent as m0.
inline void decimal_float::set_zero(void)
{
std::memcpy(&M_data, &constants[m0], sizeof(decimal_float_data));
M_data.mantissa[0] = 0;
}
// Divide the value of this object by two in one of two possible ways:
// If `decrement_exponent' is true - then decrement the exponent by
// one and multiply the mantissa with five. Otherwise just divide
// the mantissa by two.
void decimal_float::divide_by_two(bool decrement_exponent)
{
if (decrement_exponent)
{
for (int i = 0; i < mantissa_size_c; ++i)
M_data.mantissa[i] *= 5;
M_do_carry();
--M_data.exponent;
}
else
{
unsigned long prev_borrow = M_data.mantissa[mantissa_size_c - 1] % 2;
if ((M_data.mantissa[mantissa_size_c - 1] /= 2) < 1000)
M_data.max_precision_reached = false;
for (int i = mantissa_size_c - 2; i >= 0; --i)
{
unsigned long borrow = M_data.mantissa[i] % 2;
M_data.mantissa[i] /= 2;
M_data.mantissa[i] += prev_borrow * 5000;
prev_borrow = borrow;
}
if (prev_borrow)
{
// Round off.
if (++M_data.mantissa[0] == 10000)
M_do_carry();
}
}
}
// If possible, multiply the mantissa with 10 and
// decrement the exponent with one. This is used
// to keep the exponent of this object equal to
// another object that is being divided by two.
bool decimal_float::decrement_exponent(void)
{
if (M_data.max_precision_reached)
return false;
for (int i = 0; i < mantissa_size_c; ++i)
M_data.mantissa[i] *= 10;
M_do_carry();
if (M_data.mantissa[mantissa_size_c - 1] >= 1000)
M_data.max_precision_reached = true;
--M_data.exponent;
return true;
}
// Add two decimal_floats that have the same exponent.
decimal_float& decimal_float::operator+=(decimal_float const& term)
{
// assert(M_data.exponent == term.M_data.exponent);
for (int i = 0; i < mantissa_size_c; ++i)
M_data.mantissa[i] += term.M_data.mantissa[i];
M_do_carry();
return *this;
}
// The real work. Multiply this object with `factor'.
decimal_float& decimal_float::operator*=(decimal_float const& factor)
{
// Count the number of most-significant mantissa elements (digits)
// that contain zero (of either factor), but stop counting if we reach
// mantissa_size_c - 1.
int zero_digits = 0;
while (M_data.mantissa[mantissa_size_c - 1 - zero_digits] == 0)
if (++zero_digits == mantissa_size_c - 1)
break;
if (zero_digits < mantissa_size_c - 1)
{
int offset = mantissa_size_c - 1 + zero_digits;
while (factor.M_data.mantissa[offset - zero_digits] == 0)
if (++zero_digits == mantissa_size_c - 1)
break;
}
// Set `this_mantissa' to point to the mantissa of this object;
// make a copy only when we would overwrite its values when
// still needed below.
unsigned long tmp_mantissa[mantissa_size_c];
unsigned long* this_mantissa;
if (zero_digits == 0)
this_mantissa = M_data.mantissa;
else
{
std::memcpy(tmp_mantissa, M_data.mantissa, sizeof(tmp_mantissa));
this_mantissa = tmp_mantissa;
}
// Set lss (least significant (loop) size, but don't ask me why it is
// called that way - it gets a bit complicated here) to, heh, what works.
int lss = mantissa_size_c - 1 - zero_digits;
// Now hold your breath...
M_data.exponent += factor.M_data.exponent + 4 * lss;
unsigned long sum = 0;
for (int i = 0; i < lss; ++i)
sum += this_mantissa[i] * factor.M_data.mantissa[lss - 1 - i];
sum += 5000; // Round off.
sum /= 10000;
for (int j = 0; j < mantissa_size_c; ++j)
{
int loop_bgn = std::max(0, lss + j - (mantissa_size_c - 1));
int loop_end = std::min(mantissa_size_c - 1, lss + j);
for (int i = loop_bgn; i <= loop_end; ++i)
sum += this_mantissa[i] * factor.M_data.mantissa[lss + j - i];
M_data.mantissa[j] = sum;
sum /= 10000;
M_data.mantissa[j] -= 10000 * sum;
}
// ... ahhh. Ok. And do overflow management when needed.
if (sum > 0)
M_do_overflow(sum);
return *this;
}
// Print to `buf', writes: "<digit>.<digits>e<sign><exponent>\0".
// sizeof(buf) must be at least 7 larger than `precision':
// strlen(<digit><digits>) <= precision.
// strlen(.e<sign><exponent>) == 6, plus one for the trailing '\0'.
void decimal_float::print_to_with_precision(char* buf, int precision) const
{
// First do the round off.
decimal_float tmp(*this);
if (!M_data.max_precision_reached)
{
// In this case we are probably exact, so we
// don't really need to round off. Because leading
// zeroes are not printed, add number of leading 0's
// to `precision'.
for (int i = mantissa_size_c - 1; i >= 0; --i)
for(unsigned long shift = 1000; shift; shift /= 10)
{
if (M_data.mantissa[i] >= shift)
{
i = 0;
break;
}
++precision;
}
}
int e = 4 * mantissa_size_c - 1;
if (precision < mantissa_size_c * 4)
{
int cut = e - precision;
int cuti = cut / 4;
int cutr = cut % 4;
unsigned long shift = 10;
while(cutr--)
shift *= 10;
tmp.M_data.mantissa[cuti] += shift / 2; // Round off.
if (tmp.M_data.mantissa[cuti] >= 10000)
tmp.M_do_carry();
}
bool leading = true;
char* p = buf;
int tz = 0;
for (int i = mantissa_size_c - 1; i >= 0 && precision; --i)
{
unsigned long digit = tmp.M_data.mantissa[i];
for(int shift = 1000; shift; shift /= 10)
{
int d = digit / shift;
digit -= d * shift;
if (leading && d != 0)
leading = false;
if (leading) // Suppress leading zeroes.
--e;
else
{
if (d == 0) // Suppress and count trailing zeroes.
++tz;
else
{
if (p == buf + 1)
*p++ = '.';
while(tz--)
*p++ = '0';
*p++ = d + '0';
tz = 0;
}
if (--precision == 0)
break;
}
}
}
e += tmp.M_data.exponent;
if (e != 0)
{
*p++ = 'e';
if (e > 0)
*p++ = '+';
else
{
*p++ = '-';
e = -e;
}
int shift = 100;
leading = true;
while(shift)
{
int d = e / shift;
e -= d * shift;
if (leading && d != 0)
leading = false;
if (!leading)
*p++ = '0' + d;
shift /= 10;
}
}
*p = 0;
}
// print_IEEE_fp(buf, words, nbits_exponent, nbits_fraction, precision)
//
// buf : Output buffer, the result is written to this buffer
// and terminated with a trailing '\0'. The size of
// this buffer must be at least `precision + 7'.
// words : A pointer to an array with unsigned integers. Only
// the 32 least significant bits of each element are
// used. The first element contains the word with the
// most significant bits. Bit 31 in each element
// represents the most significant bit of that 32-bit
// word. See the description of IEEE 754-1985 for
// the exact meaning. Basically they mean:
// SEEEEEEEEMMMMMMMMMMMMMMMMMMMM, where S is the sign
// bit, EEEEEEEE the exponent and MMMMMMMMMMMMMMMMMMMM
// the mantissa.
// nbits_exponent : The number of bits in `words' that represent the
// exponent.
// nbits_fraction : The total number of bits in `words' representing the
// mantissa, a value larger than 52 will result in
// inaccurate output.
// precision : The maximum number of digits in the mantissa
// (including the first digit before the dot) that
// will be written to `buf'. This precision should
// correspond to the accuracy given by `nbits_fraction'
// of course.
void print_IEEE_fp(char* buf, unsigned long* words,
int nbits_exponent, int nbits_fraction, int precision)
{
// This function was written using
// http://www.psc.edu/general/software/packages/ieee/ieee.html
// as reference for the IEEE 754-1985 standard.
// assert( nbits_fraction <= 52 && nbits_exponent <= 11 &&
// nbits_exponent >= 5 && precision <= 17 );
unsigned long sign_mask = 1 << nbits_exponent;
unsigned long exponent_mask = sign_mask - 1;
unsigned long sign_and_exponent = words[0] >> (31 - nbits_exponent);
unsigned long exponent = sign_and_exponent & exponent_mask;
int nelem_fraction = (nbits_fraction + nbits_exponent) / 32 + 1;
unsigned long mask_first_elem = 0xffffffffUL >> (nbits_exponent + 1);
unsigned long mask_last_elem = ~((1UL << (nelem_fraction * 32 -
nbits_fraction - nbits_exponent - 1)) - 1);
unsigned long fraction_nonzero = (words[0] & mask_first_elem);
if (nelem_fraction == 1)
fraction_nonzero &= mask_last_elem;
else
{
fraction_nonzero |= (words[nelem_fraction - 1] & mask_last_elem);
for (int i = 1; i < nelem_fraction - 1; ++i)
fraction_nonzero |= words[i];
}
if (exponent == exponent_mask && fraction_nonzero)
{
strcpy(buf, "nan");
return;
}
if ((sign_and_exponent & sign_mask))
*buf++ = '-';
if (exponent == exponent_mask && !fraction_nonzero)
{
strcpy(buf, "inf");
return;
}
bool normalized = true;
if (exponent == 0)
{
if (!fraction_nonzero)
{
strcpy(buf, "0");
return;
}
else
{
normalized = false;
exponent = 1;
}
}
decimal_float result;
if (normalized)
result.set_2pow(m0); // 1.0 ; The 1 in (1.F)
else
result.set_zero(); // 0.0 ; The 0 in (0.F)
decimal_float bit;
bit.set_2pow(m1); // 0.5 ; 2 ** (-bit_cnt - 1)
unsigned long mask = 0x40000000 >> nbits_exponent;
for (int bit_cnt = 0; bit_cnt < nbits_fraction; ++bit_cnt)
{
if ((*words & mask))
result += bit;
bool success = result.decrement_exponent();
bit.divide_by_two(success); // Keep exponents equal for easy addition.
if (!(mask >>= 1))
{
mask = 0x80000000;
++words;
}
}
decimal_float two_pow_exponent;
two_pow_exponent.set_expstart(nbits_exponent);
// 2 ** (1 - 2 ** (nbits_exponent - 1)),
// where 1 - 2 ** (nbits_exponent - 1) is
// the two's-complement exponent 'offset'.
mask = 1 << (nbits_exponent - 1);
for (int bit_cnt = nbits_exponent - 1; bit_cnt >= 0; --bit_cnt)
{
if ((exponent & mask))
{
bit.set_2pow2pow(bit_cnt); // 2 ** (2 ** bit_cnt)
two_pow_exponent *= bit;
}
mask >>= 1;
}
result *= two_pow_exponent;
result.print_to_with_precision(buf, precision);
}
} // namespace
namespace libcwd {
#ifdef STANDALONE
static char const* main_in;
#endif
namespace _private_ {
class implementation_details : public __gnu_cxx::demangler::implementation_details {
public:
implementation_details(unsigned int flags) : __gnu_cxx::demangler::implementation_details(flags) { }
protected:
virtual bool
decode_real(char* output, unsigned long* input, size_t size_of_real) const;
};
// GNU/Linux uses IEEE encoding for floats.
bool
implementation_details::decode_real(char* output, unsigned long* input, size_t size_of_real) const
{
if (size_of_real != 4 && size_of_real !=8) // Only decode single and double precision IEEE.
return false;
if (size_of_real == 8)
print_IEEE_fp(output, input, 11, 52, 17);
else
print_IEEE_fp(output, input, 8, 23, 8);
return true;
}
#if CWDEBUG_ALLOC
typedef __gnu_cxx::demangler::session<internal_allocator> session_type;
#else
typedef __gnu_cxx::demangler::session<std::allocator<char> > session_type;
#endif
//
// demangle_symbol
//
// Demangle `input' and append to `output'.
// `input' should be a mangled_function_name as for instance returned
// by `libcwd::pc_mangled_function_name'.
//
void demangle_symbol(char const* input, internal_string& output)
{
#if CWDEBUG_DEBUGM
LIBCWD_TSD_DECLARATION;
LIBCWD_ASSERT( __libcwd_tsd.internal );
#endif
#ifdef STANDALONE
if (input != main_in)
Debug( dc::demangler.off() );
#endif
_GLIBCXX_DEMANGLER_DOUT(dc::demangler, "Entering demangle_symbol(\"" << input << "\")");
if (input == NULL)
{
output += "(null)";
#ifdef STANDALONE
if (input != main_in)
Debug( dc::demangler.on() );
#endif
return;
}
//
// <mangled-name> ::= _Z <encoding>
// <mangled-name> ::= _GLOBAL_ _<type>_ <disambiguation part> // GNU extension, <type> can be I or D.
//
bool failure = (input[0] != '_');
if (!failure)
{
if (input[1] == 'Z')
{
// C++ name?
implementation_details id(implementation_details::style_void);
int cnt = session_type::decode_encoding(output, input + 2, INT_MAX, id);
if (cnt < 0 || input[cnt + 2] != 0)
failure = true;
}
else if (input[1] == 'G')
{
// Possible _GLOBAL__ extension?
if (!std::strncmp(input, "_GLOBAL__", 9) && (input[9] == 'D' || input[9] == 'I') && input[10] == '_')
{
if (input[9] == 'D')
output.assign("global destructors keyed to ", 28);
else
output.assign("global constructors keyed to ", 29);
// Output the disambiguation part as-is.
output += input + 11;
}
else
failure = true;
}
else
failure = true;
}
if (failure)
output.assign(input, strlen(input)); // Failure to demangle, return the mangled name.
#ifdef STANDALONE
if (input != main_in)
Debug( dc::demangler.on() );
#endif
}
//
// demangle_type
//
// Demangle `input' and append to `output'.
// `input' should be a mangled type as for returned
// by the stdc++ `typeinfo::name()'.
//
void demangle_type(char const* input, internal_string& output)
{
#if CWDEBUG_DEBUGM
LIBCWD_TSD_DECLARATION;
LIBCWD_ASSERT( __libcwd_tsd.internal );
#endif
#ifdef STANDALONE
if (input != main_in)
Debug( dc::demangler.off() );
#endif
_GLIBCXX_DEMANGLER_DOUT(dc::demangler, "Entering demangle_type(\"" << input << "\")");
if (input == NULL)
{
output += "(null)";
#ifdef STANDALONE
if (input != main_in)
Debug( dc::demangler.on() );
#endif
return;
}
implementation_details id(implementation_details::style_void);
session_type demangler_session(input, INT_MAX, id);
if (!demangler_session.decode_type(output) || demangler_session.remaining_input_characters())
output.assign(input, strlen(input)); // Failure to demangle, return the mangled type name.
#ifdef STANDALONE
if (input != main_in)
Debug( dc::demangler.on() );
#endif
}
} // namespace _private_
} // namespace libcwd
#ifdef STANDALONE
#include <iostream>
int main(int argc, char* argv[])
{
Debug( libcw_do.on() );
Debug( dc::demangler.on() );
std::string out;
libcwd::main_in = argv[1];
libcwd::demangle_symbol(argv[1], out);
std::cout << out << std::endl;
return 0;
}
#endif // STANDALONE
namespace libcwd {
/** \addtogroup group_demangle */
/** \{ */
/**
* \brief Demangle mangled symbol name \p input and write the result to string \p output.
*/
void demangle_symbol(char const* input, std::string& output)
{
LIBCWD_TSD_DECLARATION;
_private_::set_alloc_checking_off(LIBCWD_TSD);
{
_private_::internal_string result;
_private_::demangle_symbol(input, result);
_private_::set_alloc_checking_on(LIBCWD_TSD);
output.append(result.data(), result.size());
_private_::set_alloc_checking_off(LIBCWD_TSD);
}
_private_::set_alloc_checking_on(LIBCWD_TSD);
}
/**
* \brief Demangle mangled type name \p input and write the result to string \p output.
*/
void demangle_type(char const* input, std::string& output)
{
LIBCWD_TSD_DECLARATION;
_private_::set_alloc_checking_off(LIBCWD_TSD);
{
_private_::internal_string result;
_private_::demangle_type(input, result);
_private_::set_alloc_checking_on(LIBCWD_TSD);
output.append(result.data(), result.size());
_private_::set_alloc_checking_off(LIBCWD_TSD);
}
_private_::set_alloc_checking_on(LIBCWD_TSD);
}
/** \} */
} // namespace libcwd
|