Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5134 serge 1
// Debugging mode support code -*- C++ -*-
2
 
3
// Copyright (C) 2003-2013 Free Software Foundation, Inc.
4
//
5
// This file is part of the GNU ISO C++ Library.  This library is free
6
// software; you can redistribute it and/or modify it under the
7
// terms of the GNU General Public License as published by the
8
// Free Software Foundation; either version 3, or (at your option)
9
// any later version.
10
 
11
// This library is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
// GNU General Public License for more details.
15
 
16
// Under Section 7 of GPL version 3, you are granted additional
17
// permissions described in the GCC Runtime Library Exception, version
18
// 3.1, as published by the Free Software Foundation.
19
 
20
// You should have received a copy of the GNU General Public License and
21
// a copy of the GCC Runtime Library Exception along with this program;
22
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23
// .
24
 
25
#include 
26
#include 
27
#include 
28
#include 
29
#include 
30
#include 
31
#include 
32
#include 
33
#include 
34
#include 
35
#include 
36
#include 
37
 
38
using namespace std;
39
 
40
namespace
41
{
42
  /** Returns different instances of __mutex depending on the passed address
43
   *  in order to limit contention without breaking current library binary
44
   *  compatibility. */
45
  __gnu_cxx::__mutex&
46
  get_safe_base_mutex(void* __address)
47
  {
48
    const size_t mask = 0xf;
49
    static __gnu_cxx::__mutex safe_base_mutex[mask + 1];
50
    const size_t index = _Hash_impl::hash(__address) & mask;
51
    return safe_base_mutex[index];
52
  }
53
 
54
  void
55
  swap_its(__gnu_debug::_Safe_sequence_base& __lhs,
56
	   __gnu_debug::_Safe_iterator_base*& __lhs_its,
57
	   __gnu_debug::_Safe_sequence_base& __rhs,
58
	   __gnu_debug::_Safe_iterator_base*& __rhs_its)
59
  {
60
    swap(__lhs_its, __rhs_its);
61
    __gnu_debug::_Safe_iterator_base* __iter;
62
    for (__iter = __rhs_its; __iter; __iter = __iter->_M_next)
63
      __iter->_M_sequence = &__rhs;
64
    for (__iter = __lhs_its; __iter; __iter = __iter->_M_next)
65
      __iter->_M_sequence = &__lhs;
66
  }
67
 
68
  void
69
  swap_seq(__gnu_debug::_Safe_sequence_base& __lhs,
70
	   __gnu_debug::_Safe_sequence_base& __rhs)
71
  {
72
    swap(__lhs._M_version, __rhs._M_version);
73
    swap_its(__lhs, __lhs._M_iterators,
74
	     __rhs, __rhs._M_iterators);
75
    swap_its(__lhs, __lhs._M_const_iterators,
76
	     __rhs, __rhs._M_const_iterators);
77
  }
78
 
79
  void
80
  swap_ucont(__gnu_debug::_Safe_unordered_container_base& __lhs,
81
	    __gnu_debug::_Safe_unordered_container_base& __rhs)
82
  {
83
    swap_seq(__lhs, __rhs);
84
    swap_its(__lhs, __lhs._M_local_iterators,
85
	     __rhs, __rhs._M_local_iterators);
86
    swap_its(__lhs, __lhs._M_const_local_iterators,
87
	     __rhs, __rhs._M_const_local_iterators);
88
  }
89
 
90
  void
91
  detach_all(__gnu_debug::_Safe_iterator_base* __iter)
92
  {
93
    for (; __iter;)
94
      {
95
	__gnu_debug::_Safe_iterator_base* __old = __iter;
96
	__iter = __iter->_M_next;
97
	__old->_M_reset();
98
      }
99
  }
100
} // anonymous namespace
101
 
102
namespace __gnu_debug
103
{
104
  const char* _S_debug_messages[] =
105
  {
106
    // General Checks
107
    "function requires a valid iterator range [%1.name;, %2.name;)",
108
    "attempt to insert into container with a singular iterator",
109
    "attempt to insert into container with an iterator"
110
    " from a different container",
111
    "attempt to erase from container with a %2.state; iterator",
112
    "attempt to erase from container with an iterator"
113
    " from a different container",
114
    "attempt to subscript container with out-of-bounds index %2;,"
115
    " but container only holds %3; elements",
116
    "attempt to access an element in an empty container",
117
    "elements in iterator range [%1.name;, %2.name;)"
118
    " are not partitioned by the value %3;",
119
    "elements in iterator range [%1.name;, %2.name;)"
120
    " are not partitioned by the predicate %3; and value %4;",
121
    "elements in iterator range [%1.name;, %2.name;) are not sorted",
122
    "elements in iterator range [%1.name;, %2.name;)"
123
    " are not sorted according to the predicate %3;",
124
    "elements in iterator range [%1.name;, %2.name;) do not form a heap",
125
    "elements in iterator range [%1.name;, %2.name;)"
126
    " do not form a heap with respect to the predicate %3;",
127
    // std::bitset checks
128
    "attempt to write through a singular bitset reference",
129
    "attempt to read from a singular bitset reference",
130
    "attempt to flip a singular bitset reference",
131
    // std::list checks
132
    "attempt to splice a list into itself",
133
    "attempt to splice lists with unequal allocators",
134
    "attempt to splice elements referenced by a %1.state; iterator",
135
    "attempt to splice an iterator from a different container",
136
    "splice destination %1.name;"
137
    " occurs within source range [%2.name;, %3.name;)",
138
    // iterator checks
139
    "attempt to initialize an iterator that will immediately become singular",
140
    "attempt to copy-construct an iterator from a singular iterator",
141
    "attempt to construct a constant iterator"
142
    " from a singular mutable iterator",
143
    "attempt to copy from a singular iterator",
144
    "attempt to dereference a %1.state; iterator",
145
    "attempt to increment a %1.state; iterator",
146
    "attempt to decrement a %1.state; iterator",
147
    "attempt to subscript a %1.state; iterator %2; step from"
148
    " its current position, which falls outside its dereferenceable range",
149
    "attempt to advance a %1.state; iterator %2; steps,"
150
    " which falls outside its valid range",
151
    "attempt to retreat a %1.state; iterator %2; steps,"
152
    " which falls outside its valid range",
153
    "attempt to compare a %1.state; iterator to a %2.state; iterator",
154
    "attempt to compare iterators from different sequences",
155
    "attempt to order a %1.state; iterator to a %2.state; iterator",
156
    "attempt to order iterators from different sequences",
157
    "attempt to compute the difference between a %1.state;"
158
    " iterator to a %2.state; iterator",
159
    "attempt to compute the different between two iterators"
160
    " from different sequences",
161
    // istream_iterator
162
    "attempt to dereference an end-of-stream istream_iterator",
163
    "attempt to increment an end-of-stream istream_iterator",
164
    // ostream_iterator
165
    "attempt to output via an ostream_iterator with no associated stream",
166
    // istreambuf_iterator
167
    "attempt to dereference an end-of-stream istreambuf_iterator"
168
    " (this is a GNU extension)",
169
    "attempt to increment an end-of-stream istreambuf_iterator",
170
    // std::forward_list
171
    "attempt to insert into container after an end iterator",
172
    "attempt to erase from container after a %2.state; iterator not followed"
173
    " by a dereferenceable one",
174
    "function requires a valid iterator range (%2.name;, %3.name;)"
175
    ", \"%2.name;\" shall be before and not equal to \"%3.name;\"",
176
    // std::unordered_container::local_iterator
177
    "attempt to compare local iterators from different unordered container"
178
    " buckets",
179
    "function requires a non-empty iterator range [%1.name;, %2.name;)",
180
    "attempt to self move assign",
181
    "attempt to access container with out-of-bounds bucket index %2;,"
182
    " container only holds %3; buckets",
183
    "load factor shall be positive",
184
    "allocators must be equal"
185
  };
186
 
187
  void
188
  _Safe_sequence_base::
189
  _M_detach_all()
190
  {
191
    __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
192
    detach_all(_M_iterators);
193
    _M_iterators = 0;
194
 
195
    detach_all(_M_const_iterators);
196
    _M_const_iterators = 0;
197
  }
198
 
199
  void
200
  _Safe_sequence_base::
201
  _M_detach_singular()
202
  {
203
    __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
204
    for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
205
      {
206
	_Safe_iterator_base* __old = __iter;
207
	__iter = __iter->_M_next;
208
	if (__old->_M_singular())
209
	  __old->_M_detach_single();
210
      }
211
 
212
    for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;)
213
      {
214
	_Safe_iterator_base* __old = __iter2;
215
	__iter2 = __iter2->_M_next;
216
	if (__old->_M_singular())
217
	  __old->_M_detach_single();
218
      }
219
  }
220
 
221
  void
222
  _Safe_sequence_base::
223
  _M_revalidate_singular()
224
  {
225
    __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
226
    for (_Safe_iterator_base* __iter = _M_iterators; __iter;
227
	 __iter = __iter->_M_next)
228
      __iter->_M_version = _M_version;
229
 
230
    for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;
231
	 __iter2 = __iter2->_M_next)
232
      __iter2->_M_version = _M_version;
233
  }
234
 
235
  void
236
  _Safe_sequence_base::
237
  _M_swap(_Safe_sequence_base& __x)
238
  {
239
    // We need to lock both sequences to swap
240
    using namespace __gnu_cxx;
241
    __mutex *__this_mutex = &_M_get_mutex();
242
    __mutex *__x_mutex = &__x._M_get_mutex();
243
    if (__this_mutex == __x_mutex)
244
      {
245
	__scoped_lock __lock(*__this_mutex);
246
	swap_seq(*this, __x);
247
      }
248
    else
249
      {
250
	__scoped_lock __l1(__this_mutex < __x_mutex
251
			     ? *__this_mutex : *__x_mutex);
252
	__scoped_lock __l2(__this_mutex < __x_mutex
253
			     ? *__x_mutex : *__this_mutex);
254
	swap_seq(*this, __x);
255
      }
256
  }
257
 
258
  __gnu_cxx::__mutex&
259
  _Safe_sequence_base::
260
  _M_get_mutex() throw ()
261
  { return get_safe_base_mutex(this); }
262
 
263
  void
264
  _Safe_sequence_base::
265
  _M_attach(_Safe_iterator_base* __it, bool __constant)
266
  {
267
    __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
268
    _M_attach_single(__it, __constant);
269
  }
270
 
271
  void
272
  _Safe_sequence_base::
273
  _M_attach_single(_Safe_iterator_base* __it, bool __constant) throw ()
274
  {
275
    _Safe_iterator_base*& __its =
276
      __constant ? _M_const_iterators : _M_iterators;
277
    __it->_M_next = __its;
278
    if (__it->_M_next)
279
      __it->_M_next->_M_prior = __it;
280
    __its = __it;
281
  }
282
 
283
  void
284
  _Safe_sequence_base::
285
  _M_detach(_Safe_iterator_base* __it)
286
  {
287
    // Remove __it from this sequence's list
288
    __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
289
    _M_detach_single(__it);
290
  }
291
 
292
  void
293
  _Safe_sequence_base::
294
  _M_detach_single(_Safe_iterator_base* __it) throw ()
295
  {
296
    // Remove __it from this sequence's list
297
    __it->_M_unlink();
298
    if (_M_const_iterators == __it)
299
      _M_const_iterators = __it->_M_next;
300
    if (_M_iterators == __it)
301
      _M_iterators = __it->_M_next;
302
  }
303
 
304
  void
305
  _Safe_iterator_base::
306
  _M_attach(_Safe_sequence_base* __seq, bool __constant)
307
  {
308
    _M_detach();
309
 
310
    // Attach to the new sequence (if there is one)
311
    if (__seq)
312
      {
313
	_M_sequence = __seq;
314
	_M_version = _M_sequence->_M_version;
315
	_M_sequence->_M_attach(this, __constant);
316
      }
317
  }
318
 
319
  void
320
  _Safe_iterator_base::
321
  _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw ()
322
  {
323
    _M_detach_single();
324
 
325
    // Attach to the new sequence (if there is one)
326
    if (__seq)
327
      {
328
	_M_sequence = __seq;
329
	_M_version = _M_sequence->_M_version;
330
	_M_sequence->_M_attach_single(this, __constant);
331
      }
332
  }
333
 
334
  void
335
  _Safe_iterator_base::
336
  _M_detach()
337
  {
338
    if (_M_sequence)
339
      _M_sequence->_M_detach(this);
340
 
341
    _M_reset();
342
  }
343
 
344
  void
345
  _Safe_iterator_base::
346
  _M_detach_single() throw ()
347
  {
348
    if (_M_sequence)
349
      _M_sequence->_M_detach_single(this);
350
 
351
    _M_reset();
352
  }
353
 
354
  void
355
  _Safe_iterator_base::
356
  _M_reset() throw ()
357
  {
358
    _M_sequence = 0;
359
    _M_version = 0;
360
    _M_prior = 0;
361
    _M_next = 0;
362
  }
363
 
364
  bool
365
  _Safe_iterator_base::
366
  _M_singular() const throw ()
367
  { return !_M_sequence || _M_version != _M_sequence->_M_version; }
368
 
369
  bool
370
  _Safe_iterator_base::
371
  _M_can_compare(const _Safe_iterator_base& __x) const throw ()
372
  {
373
    return (!_M_singular()
374
	    && !__x._M_singular() && _M_sequence == __x._M_sequence);
375
  }
376
 
377
  __gnu_cxx::__mutex&
378
  _Safe_iterator_base::
379
  _M_get_mutex() throw ()
380
  { return get_safe_base_mutex(_M_sequence); }
381
 
382
  _Safe_unordered_container_base*
383
  _Safe_local_iterator_base::
384
  _M_get_container() const _GLIBCXX_NOEXCEPT
385
  { return static_cast<_Safe_unordered_container_base*>(_M_sequence); }
386
 
387
  void
388
  _Safe_local_iterator_base::
389
  _M_attach(_Safe_sequence_base* __cont, bool __constant)
390
  {
391
    _M_detach();
392
 
393
    // Attach to the new container (if there is one)
394
    if (__cont)
395
      {
396
	_M_sequence = __cont;
397
	_M_version = _M_sequence->_M_version;
398
	_M_get_container()->_M_attach_local(this, __constant);
399
      }
400
  }
401
 
402
  void
403
  _Safe_local_iterator_base::
404
  _M_attach_single(_Safe_sequence_base* __cont, bool __constant) throw ()
405
  {
406
    _M_detach_single();
407
 
408
    // Attach to the new container (if there is one)
409
    if (__cont)
410
      {
411
	_M_sequence = __cont;
412
	_M_version = _M_sequence->_M_version;
413
	_M_get_container()->_M_attach_local_single(this, __constant);
414
      }
415
  }
416
 
417
  void
418
  _Safe_local_iterator_base::
419
  _M_detach()
420
  {
421
    if (_M_sequence)
422
      _M_get_container()->_M_detach_local(this);
423
 
424
    _M_reset();
425
  }
426
 
427
  void
428
  _Safe_local_iterator_base::
429
  _M_detach_single() throw ()
430
  {
431
    if (_M_sequence)
432
      _M_get_container()->_M_detach_local_single(this);
433
 
434
    _M_reset();
435
  }
436
 
437
  void
438
  _Safe_unordered_container_base::
439
  _M_detach_all()
440
  {
441
    __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
442
    detach_all(_M_iterators);
443
    _M_iterators = 0;
444
 
445
    detach_all(_M_const_iterators);
446
    _M_const_iterators = 0;
447
 
448
    detach_all(_M_local_iterators);
449
    _M_local_iterators = 0;
450
 
451
    detach_all(_M_const_local_iterators);
452
    _M_const_local_iterators = 0;
453
  }
454
 
455
  void
456
  _Safe_unordered_container_base::
457
  _M_swap(_Safe_unordered_container_base& __x)
458
  {
459
    // We need to lock both containers to swap
460
    using namespace __gnu_cxx;
461
    __mutex *__this_mutex = &_M_get_mutex();
462
    __mutex *__x_mutex = &__x._M_get_mutex();
463
    if (__this_mutex == __x_mutex)
464
      {
465
	__scoped_lock __lock(*__this_mutex);
466
	swap_ucont(*this, __x);
467
      }
468
    else
469
      {
470
	__scoped_lock __l1(__this_mutex < __x_mutex
471
			     ? *__this_mutex : *__x_mutex);
472
	__scoped_lock __l2(__this_mutex < __x_mutex
473
			     ? *__x_mutex : *__this_mutex);
474
	swap_ucont(*this, __x);
475
      }
476
  }
477
 
478
  void
479
  _Safe_unordered_container_base::
480
  _M_attach_local(_Safe_iterator_base* __it, bool __constant)
481
  {
482
    __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
483
    _M_attach_local_single(__it, __constant);
484
  }
485
 
486
  void
487
  _Safe_unordered_container_base::
488
  _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) throw ()
489
  {
490
    _Safe_iterator_base*& __its =
491
      __constant ? _M_const_local_iterators : _M_local_iterators;
492
    __it->_M_next = __its;
493
    if (__it->_M_next)
494
      __it->_M_next->_M_prior = __it;
495
    __its = __it;
496
  }
497
 
498
  void
499
  _Safe_unordered_container_base::
500
  _M_detach_local(_Safe_iterator_base* __it)
501
  {
502
    // Remove __it from this container's list
503
    __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
504
    _M_detach_local_single(__it);
505
  }
506
 
507
  void
508
  _Safe_unordered_container_base::
509
  _M_detach_local_single(_Safe_iterator_base* __it) throw ()
510
  {
511
    // Remove __it from this container's list
512
    __it->_M_unlink();
513
    if (_M_const_local_iterators == __it)
514
      _M_const_local_iterators = __it->_M_next;
515
    if (_M_local_iterators == __it)
516
      _M_local_iterators = __it->_M_next;
517
  }
518
 
519
  void
520
  _Error_formatter::_Parameter::
521
  _M_print_field(const _Error_formatter* __formatter, const char* __name) const
522
  {
523
    assert(this->_M_kind != _Parameter::__unused_param);
524
    const int __bufsize = 64;
525
    char __buf[__bufsize];
526
 
527
    if (_M_kind == __iterator)
528
      {
529
	if (strcmp(__name, "name") == 0)
530
	  {
531
	    assert(_M_variant._M_iterator._M_name);
532
	    __formatter->_M_print_word(_M_variant._M_iterator._M_name);
533
	  }
534
	else if (strcmp(__name, "address") == 0)
535
	  {
536
	    __formatter->_M_format_word(__buf, __bufsize, "%p",
537
					_M_variant._M_iterator._M_address);
538
	    __formatter->_M_print_word(__buf);
539
	  }
540
	else if (strcmp(__name, "type") == 0)
541
	  {
542
	    if (!_M_variant._M_iterator._M_type)
543
	      __formatter->_M_print_word("");
544
	    else
545
	      // TBD: demangle!
546
	      __formatter->_M_print_word(_M_variant._M_iterator.
547
					 _M_type->name());
548
	  }
549
	else if (strcmp(__name, "constness") == 0)
550
	  {
551
	    static const char* __constness_names[__last_constness] =
552
	      {
553
		"",
554
		"constant",
555
		"mutable"
556
	      };
557
	    __formatter->_M_print_word(__constness_names[_M_variant.
558
							 _M_iterator.
559
							 _M_constness]);
560
	  }
561
	else if (strcmp(__name, "state") == 0)
562
	  {
563
	    static const char* __state_names[__last_state] =
564
	      {
565
		"",
566
		"singular",
567
		"dereferenceable (start-of-sequence)",
568
		"dereferenceable",
569
		"past-the-end",
570
		"before-begin"
571
	      };
572
	    __formatter->_M_print_word(__state_names[_M_variant.
573
						     _M_iterator._M_state]);
574
	  }
575
	else if (strcmp(__name, "sequence") == 0)
576
	  {
577
	    assert(_M_variant._M_iterator._M_sequence);
578
	    __formatter->_M_format_word(__buf, __bufsize, "%p",
579
					_M_variant._M_iterator._M_sequence);
580
	    __formatter->_M_print_word(__buf);
581
	  }
582
	else if (strcmp(__name, "seq_type") == 0)
583
	  {
584
	    if (!_M_variant._M_iterator._M_seq_type)
585
	      __formatter->_M_print_word("");
586
	    else
587
	      // TBD: demangle!
588
	      __formatter->_M_print_word(_M_variant._M_iterator.
589
					 _M_seq_type->name());
590
	  }
591
	else
592
	  assert(false);
593
      }
594
    else if (_M_kind == __sequence)
595
      {
596
	if (strcmp(__name, "name") == 0)
597
	  {
598
	    assert(_M_variant._M_sequence._M_name);
599
	    __formatter->_M_print_word(_M_variant._M_sequence._M_name);
600
	  }
601
	else if (strcmp(__name, "address") == 0)
602
	  {
603
	    assert(_M_variant._M_sequence._M_address);
604
	    __formatter->_M_format_word(__buf, __bufsize, "%p",
605
					_M_variant._M_sequence._M_address);
606
	    __formatter->_M_print_word(__buf);
607
	  }
608
	else if (strcmp(__name, "type") == 0)
609
	  {
610
	    if (!_M_variant._M_sequence._M_type)
611
	      __formatter->_M_print_word("");
612
	    else
613
	      // TBD: demangle!
614
	      __formatter->_M_print_word(_M_variant._M_sequence.
615
					 _M_type->name());
616
	  }
617
	else
618
	  assert(false);
619
      }
620
    else if (_M_kind == __integer)
621
      {
622
	if (strcmp(__name, "name") == 0)
623
	  {
624
	    assert(_M_variant._M_integer._M_name);
625
	    __formatter->_M_print_word(_M_variant._M_integer._M_name);
626
	  }
627
	else
628
	assert(false);
629
      }
630
    else if (_M_kind == __string)
631
      {
632
	if (strcmp(__name, "name") == 0)
633
	  {
634
	    assert(_M_variant._M_string._M_name);
635
	    __formatter->_M_print_word(_M_variant._M_string._M_name);
636
	  }
637
	else
638
	  assert(false);
639
      }
640
    else
641
      {
642
	assert(false);
643
      }
644
  }
645
 
646
  void
647
  _Error_formatter::_Parameter::
648
  _M_print_description(const _Error_formatter* __formatter) const
649
  {
650
    const int __bufsize = 128;
651
    char __buf[__bufsize];
652
 
653
    if (_M_kind == __iterator)
654
      {
655
	__formatter->_M_print_word("iterator ");
656
	if (_M_variant._M_iterator._M_name)
657
	  {
658
	    __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ",
659
					_M_variant._M_iterator._M_name);
660
	    __formatter->_M_print_word(__buf);
661
	  }
662
 
663
	__formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n",
664
				    _M_variant._M_iterator._M_address);
665
	__formatter->_M_print_word(__buf);
666
	if (_M_variant._M_iterator._M_type)
667
	  {
668
	    __formatter->_M_print_word("type = ");
669
	    _M_print_field(__formatter, "type");
670
 
671
	    if (_M_variant._M_iterator._M_constness != __unknown_constness)
672
	      {
673
		__formatter->_M_print_word(" (");
674
		_M_print_field(__formatter, "constness");
675
		__formatter->_M_print_word(" iterator)");
676
	      }
677
	    __formatter->_M_print_word(";\n");
678
	  }
679
 
680
	if (_M_variant._M_iterator._M_state != __unknown_state)
681
	  {
682
	    __formatter->_M_print_word("  state = ");
683
	    _M_print_field(__formatter, "state");
684
	    __formatter->_M_print_word(";\n");
685
	  }
686
 
687
	if (_M_variant._M_iterator._M_sequence)
688
	  {
689
	    __formatter->_M_print_word("  references sequence ");
690
	    if (_M_variant._M_iterator._M_seq_type)
691
	      {
692
		__formatter->_M_print_word("with type `");
693
		_M_print_field(__formatter, "seq_type");
694
		__formatter->_M_print_word("' ");
695
	      }
696
 
697
	    __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p\n",
698
					_M_variant._M_sequence._M_address);
699
	    __formatter->_M_print_word(__buf);
700
	  }
701
	__formatter->_M_print_word("}\n");
702
      }
703
    else if (_M_kind == __sequence)
704
      {
705
	__formatter->_M_print_word("sequence ");
706
	if (_M_variant._M_sequence._M_name)
707
	  {
708
	    __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ",
709
					_M_variant._M_sequence._M_name);
710
	    __formatter->_M_print_word(__buf);
711
	  }
712
 
713
	__formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n",
714
				    _M_variant._M_sequence._M_address);
715
	__formatter->_M_print_word(__buf);
716
 
717
	if (_M_variant._M_sequence._M_type)
718
	  {
719
	    __formatter->_M_print_word("  type = ");
720
	    _M_print_field(__formatter, "type");
721
	    __formatter->_M_print_word(";\n");
722
	  }
723
	__formatter->_M_print_word("}\n");
724
      }
725
  }
726
 
727
  const _Error_formatter&
728
  _Error_formatter::_M_message(_Debug_msg_id __id) const throw ()
729
  { return this->_M_message(_S_debug_messages[__id]); }
730
 
731
  void
732
  _Error_formatter::_M_error() const
733
  {
734
    const int __bufsize = 128;
735
    char __buf[__bufsize];
736
 
737
    // Emit file & line number information
738
    _M_column = 1;
739
    _M_wordwrap = false;
740
    if (_M_file)
741
      {
742
	_M_format_word(__buf, __bufsize, "%s:", _M_file);
743
	_M_print_word(__buf);
744
	_M_column += strlen(__buf);
745
      }
746
 
747
    if (_M_line > 0)
748
      {
749
	_M_format_word(__buf, __bufsize, "%u:", _M_line);
750
	_M_print_word(__buf);
751
	_M_column += strlen(__buf);
752
      }
753
 
754
    if (_M_max_length)
755
      _M_wordwrap = true;
756
    _M_print_word("error: ");
757
 
758
    // Print the error message
759
    assert(_M_text);
760
    _M_print_string(_M_text);
761
    _M_print_word(".\n");
762
 
763
    // Emit descriptions of the objects involved in the operation
764
    _M_wordwrap = false;
765
    bool __has_noninteger_parameters = false;
766
    for (unsigned int __i = 0; __i < _M_num_parameters; ++__i)
767
      {
768
	if (_M_parameters[__i]._M_kind == _Parameter::__iterator
769
	    || _M_parameters[__i]._M_kind == _Parameter::__sequence)
770
	  {
771
	    if (!__has_noninteger_parameters)
772
	      {
773
		_M_first_line = true;
774
		_M_print_word("\nObjects involved in the operation:\n");
775
		__has_noninteger_parameters = true;
776
	      }
777
	    _M_parameters[__i]._M_print_description(this);
778
	  }
779
      }
780
 
781
    abort();
782
  }
783
 
784
  template
785
    void
786
    _Error_formatter::_M_format_word(char* __buf,
787
				     int __n __attribute__ ((__unused__)),
788
				     const char* __fmt, _Tp __s) const throw ()
789
    {
790
#ifdef _GLIBCXX_USE_C99
791
      std::snprintf(__buf, __n, __fmt, __s);
792
#else
793
      std::sprintf(__buf, __fmt, __s);
794
#endif
795
    }
796
 
797
 
798
  void
799
  _Error_formatter::_M_print_word(const char* __word) const
800
  {
801
    if (!_M_wordwrap)
802
      {
803
	fprintf(stderr, "%s", __word);
804
	return;
805
      }
806
 
807
    size_t __length = strlen(__word);
808
    if (__length == 0)
809
      return;
810
 
811
    if ((_M_column + __length < _M_max_length)
812
	|| (__length >= _M_max_length && _M_column == 1))
813
      {
814
	// If this isn't the first line, indent
815
	if (_M_column == 1 && !_M_first_line)
816
	  {
817
	    char __spacing[_M_indent + 1];
818
	    for (int i = 0; i < _M_indent; ++i)
819
	      __spacing[i] = ' ';
820
	    __spacing[_M_indent] = '\0';
821
	    fprintf(stderr, "%s", __spacing);
822
	    _M_column += _M_indent;
823
	  }
824
 
825
	fprintf(stderr, "%s", __word);
826
	_M_column += __length;
827
 
828
	if (__word[__length - 1] == '\n')
829
	  {
830
	    _M_first_line = false;
831
	    _M_column = 1;
832
	  }
833
      }
834
    else
835
      {
836
	_M_column = 1;
837
	_M_print_word("\n");
838
	_M_print_word(__word);
839
      }
840
  }
841
 
842
  void
843
  _Error_formatter::
844
  _M_print_string(const char* __string) const
845
  {
846
    const char* __start = __string;
847
    const char* __finish = __start;
848
    const int __bufsize = 128;
849
    char __buf[__bufsize];
850
 
851
    while (*__start)
852
      {
853
	if (*__start != '%')
854
	  {
855
	    // [__start, __finish) denotes the next word
856
	    __finish = __start;
857
	    while (isalnum(*__finish))
858
	      ++__finish;
859
	    if (__start == __finish)
860
	      ++__finish;
861
	    if (isspace(*__finish))
862
	      ++__finish;
863
 
864
	    const ptrdiff_t __len = __finish - __start;
865
	    assert(__len < __bufsize);
866
	    memcpy(__buf, __start, __len);
867
	    __buf[__len] = '\0';
868
	    _M_print_word(__buf);
869
	    __start = __finish;
870
 
871
	    // Skip extra whitespace
872
	    while (*__start == ' ')
873
	      ++__start;
874
 
875
	    continue;
876
	  }
877
 
878
	++__start;
879
	assert(*__start);
880
	if (*__start == '%')
881
	  {
882
	    _M_print_word("%");
883
	    ++__start;
884
	    continue;
885
	  }
886
 
887
	// Get the parameter number
888
	assert(*__start >= '1' && *__start <= '9');
889
	size_t __param = *__start - '0';
890
	--__param;
891
	assert(__param < _M_num_parameters);
892
 
893
	// '.' separates the parameter number from the field
894
	// name, if there is one.
895
	++__start;
896
	if (*__start != '.')
897
	  {
898
	    assert(*__start == ';');
899
	    ++__start;
900
	    __buf[0] = '\0';
901
	    if (_M_parameters[__param]._M_kind == _Parameter::__integer)
902
	      {
903
		_M_format_word(__buf, __bufsize, "%ld",
904
			       _M_parameters[__param]._M_variant._M_integer._M_value);
905
		_M_print_word(__buf);
906
	      }
907
	    else if (_M_parameters[__param]._M_kind == _Parameter::__string)
908
	      _M_print_string(_M_parameters[__param]._M_variant._M_string._M_value);
909
	    continue;
910
	  }
911
 
912
	// Extract the field name we want
913
	enum { __max_field_len = 16 };
914
	char __field[__max_field_len];
915
	int __field_idx = 0;
916
	++__start;
917
	while (*__start != ';')
918
	  {
919
	    assert(*__start);
920
	    assert(__field_idx < __max_field_len-1);
921
	    __field[__field_idx++] = *__start++;
922
	  }
923
	++__start;
924
	__field[__field_idx] = 0;
925
 
926
	_M_parameters[__param]._M_print_field(this, __field);
927
      }
928
  }
929
 
930
  void
931
  _Error_formatter::_M_get_max_length() const throw ()
932
  {
933
    const char* __nptr = std::getenv("GLIBCXX_DEBUG_MESSAGE_LENGTH");
934
    if (__nptr)
935
      {
936
	char* __endptr;
937
	const unsigned long __ret = std::strtoul(__nptr, &__endptr, 0);
938
	if (*__nptr != '\0' && *__endptr == '\0')
939
	  _M_max_length = __ret;
940
      }
941
  }
942
 
943
  // Instantiations.
944
  template
945
    void
946
    _Error_formatter::_M_format_word(char*, int, const char*,
947
				     const void*) const;
948
 
949
  template
950
    void
951
    _Error_formatter::_M_format_word(char*, int, const char*, long) const;
952
 
953
  template
954
    void
955
    _Error_formatter::_M_format_word(char*, int, const char*,
956
				     std::size_t) const;
957
 
958
  template
959
    void
960
    _Error_formatter::_M_format_word(char*, int, const char*,
961
				     const char*) const;
962
} // namespace __gnu_debug