File: demangle3.cc

package info (click to toggle)
libcwd 1.0.3-1
  • links: PTS
  • area: non-free
  • in suites: squeeze
  • size: 8,104 kB
  • ctags: 10,429
  • sloc: cpp: 23,337; sh: 9,798; ansic: 1,172; makefile: 848; exp: 234; awk: 11
file content (859 lines) | stat: -rw-r--r-- 26,189 bytes parent folder | download | duplicates (4)
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.&nbsp;

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