Import gcc-4.4.1
[dragonfly.git] / contrib / gcc-4.4 / libstdc++-v3 / src / debug.cc
1 // Debugging mode support code -*- C++ -*-
2
3 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009
4 // Free Software Foundation, Inc.
5 //
6 // This file is part of the GNU ISO C++ Library.  This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 3, or (at your option)
10 // any later version.
11
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16
17 // Under Section 7 of GPL version 3, you are granted additional
18 // permissions described in the GCC Runtime Library Exception, version
19 // 3.1, as published by the Free Software Foundation.
20
21 // You should have received a copy of the GNU General Public License and
22 // a copy of the GCC Runtime Library Exception along with this program;
23 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24 // <http://www.gnu.org/licenses/>.
25
26 #include <debug/debug.h>
27 #include <debug/safe_sequence.h>
28 #include <debug/safe_iterator.h>
29 #include <algorithm>
30 #include <cassert>
31 #include <cstring>
32 #include <cctype>
33 #include <cstdio>
34 #include <cstdlib>
35
36 using namespace std;
37
38 namespace
39 {
40   __gnu_cxx::__mutex&
41   get_safe_base_mutex()
42   {
43     static __gnu_cxx::__mutex safe_base_mutex;
44     return safe_base_mutex;
45   }
46 } // anonymous namespace
47
48 namespace __gnu_debug
49 {
50   const char* _S_debug_messages[] = 
51   {
52     "function requires a valid iterator range [%1.name;, %2.name;)",
53     "attempt to insert into container with a singular iterator",
54     "attempt to insert into container with an iterator"
55     " from a different container",
56     "attempt to erase from container with a %2.state; iterator",
57     "attempt to erase from container with an iterator"
58     " from a different container",
59     "attempt to subscript container with out-of-bounds index %2;,"
60     " but container only holds %3; elements",
61     "attempt to access an element in an empty container",
62     "elements in iterator range [%1.name;, %2.name;)"
63     " are not partitioned by the value %3;",
64     "elements in iterator range [%1.name;, %2.name;)"
65     " are not partitioned by the predicate %3; and value %4;",
66     "elements in iterator range [%1.name;, %2.name;) are not sorted",
67     "elements in iterator range [%1.name;, %2.name;)"
68     " are not sorted according to the predicate %3;",
69     "elements in iterator range [%1.name;, %2.name;) do not form a heap",
70     "elements in iterator range [%1.name;, %2.name;)"
71     " do not form a heap with respect to the predicate %3;",
72     "attempt to write through a singular bitset reference",
73     "attempt to read from a singular bitset reference",
74     "attempt to flip a singular bitset reference",
75     "attempt to splice a list into itself",
76     "attempt to splice lists with inequal allocators",
77     "attempt to splice elements referenced by a %1.state; iterator",
78     "attempt to splice an iterator from a different container",
79     "splice destination %1.name;"
80     " occurs within source range [%2.name;, %3.name;)",
81     "attempt to initialize an iterator that will immediately become singular",
82     "attempt to copy-construct an iterator from a singular iterator",
83     "attempt to construct a constant iterator"
84     " from a singular mutable iterator",
85     "attempt to copy from a singular iterator",
86     "attempt to dereference a %1.state; iterator",
87     "attempt to increment a %1.state; iterator",
88     "attempt to decrement a %1.state; iterator",
89     "attempt to subscript a %1.state; iterator %2; step from"
90     " its current position, which falls outside its dereferenceable range",
91     "attempt to advance a %1.state; iterator %2; steps,"
92     " which falls outside its valid range",
93     "attempt to retreat a %1.state; iterator %2; steps,"
94     " which falls outside its valid range",
95     "attempt to compare a %1.state; iterator to a %2.state; iterator",
96     "attempt to compare iterators from different sequences",
97     "attempt to order a %1.state; iterator to a %2.state; iterator",
98     "attempt to order iterators from different sequences",
99     "attempt to compute the difference between a %1.state;"
100     " iterator to a %2.state; iterator",
101     "attempt to compute the different between two iterators"
102     " from different sequences",
103     "attempt to dereference an end-of-stream istream_iterator",
104     "attempt to increment an end-of-stream istream_iterator",
105     "attempt to output via an ostream_iterator with no associated stream",
106     "attempt to dereference an end-of-stream istreambuf_iterator"
107     " (this is a GNU extension)",
108     "attempt to increment an end-of-stream istreambuf_iterator"
109   };
110
111   void
112   _Safe_sequence_base::
113   _M_detach_all()
114   {
115     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
116     for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
117       {
118         _Safe_iterator_base* __old = __iter;
119         __iter = __iter->_M_next;
120         __old->_M_detach_single();
121       }
122     
123     for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;)
124       {
125         _Safe_iterator_base* __old = __iter2;
126         __iter2 = __iter2->_M_next;
127         __old->_M_detach_single();
128       }
129   }
130
131   void
132   _Safe_sequence_base::
133   _M_detach_singular()
134   {
135     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
136     for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
137       {
138         _Safe_iterator_base* __old = __iter;
139         __iter = __iter->_M_next;
140         if (__old->_M_singular())
141           __old->_M_detach_single();
142       }
143
144     for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;)
145       {
146         _Safe_iterator_base* __old = __iter2;
147         __iter2 = __iter2->_M_next;
148         if (__old->_M_singular())
149           __old->_M_detach_single();
150       }
151   }
152
153   void
154   _Safe_sequence_base::
155   _M_revalidate_singular()
156   {
157     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
158     for (_Safe_iterator_base* __iter = _M_iterators; __iter;
159          __iter = __iter->_M_next)
160       __iter->_M_version = _M_version;
161
162     for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;
163          __iter2 = __iter2->_M_next)
164       __iter2->_M_version = _M_version;
165   }
166
167   void
168   _Safe_sequence_base::
169   _M_swap(_Safe_sequence_base& __x)
170   {
171     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
172     swap(_M_iterators, __x._M_iterators);
173     swap(_M_const_iterators, __x._M_const_iterators);
174     swap(_M_version, __x._M_version);
175     _Safe_iterator_base* __iter;
176     for (__iter = _M_iterators; __iter; __iter = __iter->_M_next)
177       __iter->_M_sequence = this;
178     for (__iter = __x._M_iterators; __iter; __iter = __iter->_M_next)
179       __iter->_M_sequence = &__x;
180     for (__iter = _M_const_iterators; __iter; __iter = __iter->_M_next)
181       __iter->_M_sequence = this;
182     for (__iter = __x._M_const_iterators; __iter; __iter = __iter->_M_next)
183       __iter->_M_sequence = &__x;
184   }
185
186   __gnu_cxx::__mutex&
187   _Safe_sequence_base::
188   _M_get_mutex()
189   { return get_safe_base_mutex(); }
190
191   void
192   _Safe_iterator_base::
193   _M_attach(_Safe_sequence_base* __seq, bool __constant)
194   {
195     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
196     _M_attach_single(__seq, __constant);
197   }
198   
199   void
200   _Safe_iterator_base::
201   _M_attach_single(_Safe_sequence_base* __seq, bool __constant)
202   {
203     _M_detach_single();
204     
205     // Attach to the new sequence (if there is one)
206     if (__seq)
207       {
208         _M_sequence = __seq;
209         _M_version = _M_sequence->_M_version;
210         _M_prior = 0;
211         if (__constant)
212           {
213             _M_next = _M_sequence->_M_const_iterators;
214             if (_M_next)
215               _M_next->_M_prior = this;
216             _M_sequence->_M_const_iterators = this;
217           }
218         else
219           {
220             _M_next = _M_sequence->_M_iterators;
221             if (_M_next)
222               _M_next->_M_prior = this;
223             _M_sequence->_M_iterators = this;
224           }
225       }
226   }
227
228   void
229   _Safe_iterator_base::
230   _M_detach()
231   {
232     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
233     _M_detach_single();
234   }
235
236   void
237   _Safe_iterator_base::
238   _M_detach_single()
239   {
240     if (_M_sequence)
241       {
242         // Remove us from this sequence's list
243         if (_M_prior) 
244           _M_prior->_M_next = _M_next;
245         if (_M_next)  
246           _M_next->_M_prior = _M_prior;
247         
248         if (_M_sequence->_M_const_iterators == this)
249           _M_sequence->_M_const_iterators = _M_next;
250         if (_M_sequence->_M_iterators == this)
251           _M_sequence->_M_iterators = _M_next;
252       }
253
254     _M_sequence = 0;
255     _M_version = 0;
256     _M_prior = 0;
257     _M_next = 0;
258   }
259
260   bool
261   _Safe_iterator_base::
262   _M_singular() const
263   { return !_M_sequence || _M_version != _M_sequence->_M_version; }
264     
265   bool
266   _Safe_iterator_base::
267   _M_can_compare(const _Safe_iterator_base& __x) const
268   {
269     return (!_M_singular() 
270             && !__x._M_singular() && _M_sequence == __x._M_sequence);
271   }
272
273   __gnu_cxx::__mutex&
274   _Safe_iterator_base::
275   _M_get_mutex()
276   { return get_safe_base_mutex(); }
277
278   void
279   _Error_formatter::_Parameter::
280   _M_print_field(const _Error_formatter* __formatter, const char* __name) const
281   {
282     assert(this->_M_kind != _Parameter::__unused_param);
283     const int __bufsize = 64;
284     char __buf[__bufsize];
285     
286     if (_M_kind == __iterator)
287       {
288         if (strcmp(__name, "name") == 0)
289           {
290             assert(_M_variant._M_iterator._M_name);
291             __formatter->_M_print_word(_M_variant._M_iterator._M_name);
292           }
293         else if (strcmp(__name, "address") == 0)
294           {
295             __formatter->_M_format_word(__buf, __bufsize, "%p", 
296                                         _M_variant._M_iterator._M_address);
297             __formatter->_M_print_word(__buf);
298           }
299         else if (strcmp(__name, "type") == 0)
300           {
301             assert(_M_variant._M_iterator._M_type);
302             // TBD: demangle!
303             __formatter->_M_print_word(_M_variant._M_iterator._M_type->name());
304           }
305         else if (strcmp(__name, "constness") == 0)
306           {
307             static const char* __constness_names[__last_constness] =
308               {
309                 "<unknown>",
310                 "constant",
311                 "mutable"
312               };
313             __formatter->_M_print_word(__constness_names[_M_variant._M_iterator._M_constness]);
314           }
315         else if (strcmp(__name, "state") == 0)
316           {
317             static const char* __state_names[__last_state] = 
318               {
319                 "<unknown>",
320                 "singular",
321                 "dereferenceable (start-of-sequence)",
322                 "dereferenceable",
323                 "past-the-end"
324               };
325             __formatter->_M_print_word(__state_names[_M_variant._M_iterator._M_state]);
326           }
327         else if (strcmp(__name, "sequence") == 0)
328           {
329             assert(_M_variant._M_iterator._M_sequence);
330             __formatter->_M_format_word(__buf, __bufsize, "%p", 
331                                         _M_variant._M_iterator._M_sequence);
332             __formatter->_M_print_word(__buf);
333           }
334         else if (strcmp(__name, "seq_type") == 0)
335           {
336             // TBD: demangle!
337             assert(_M_variant._M_iterator._M_seq_type);
338             __formatter->_M_print_word(_M_variant._M_iterator._M_seq_type->name());
339           }
340         else
341           assert(false);
342       }
343     else if (_M_kind == __sequence)
344       {
345         if (strcmp(__name, "name") == 0)
346           {
347             assert(_M_variant._M_sequence._M_name);
348             __formatter->_M_print_word(_M_variant._M_sequence._M_name);
349           }
350         else if (strcmp(__name, "address") == 0)
351           {
352             assert(_M_variant._M_sequence._M_address);
353             __formatter->_M_format_word(__buf, __bufsize, "%p", 
354                                         _M_variant._M_sequence._M_address);
355             __formatter->_M_print_word(__buf);
356           }
357         else if (strcmp(__name, "type") == 0)
358           {
359             // TBD: demangle!
360             assert(_M_variant._M_sequence._M_type);
361             __formatter->_M_print_word(_M_variant._M_sequence._M_type->name());
362           }
363         else
364           assert(false);
365       }
366     else if (_M_kind == __integer)
367       {
368         if (strcmp(__name, "name") == 0)
369           {
370             assert(_M_variant._M_integer._M_name);
371             __formatter->_M_print_word(_M_variant._M_integer._M_name);
372           }
373         else
374         assert(false);
375       }
376     else if (_M_kind == __string)
377       {
378         if (strcmp(__name, "name") == 0)
379           {
380             assert(_M_variant._M_string._M_name);
381             __formatter->_M_print_word(_M_variant._M_string._M_name);
382           }
383         else
384           assert(false);
385       }
386     else
387       {
388         assert(false);
389       }
390   }
391   
392   void
393   _Error_formatter::_Parameter::
394   _M_print_description(const _Error_formatter* __formatter) const
395   {
396     const int __bufsize = 128;
397     char __buf[__bufsize];
398     
399     if (_M_kind == __iterator)
400       {
401         __formatter->_M_print_word("iterator ");
402         if (_M_variant._M_iterator._M_name)
403           {
404             __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ", 
405                                         _M_variant._M_iterator._M_name);
406             __formatter->_M_print_word(__buf);
407           }
408         
409         __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n", 
410                                     _M_variant._M_iterator._M_address);
411         __formatter->_M_print_word(__buf);
412         if (_M_variant._M_iterator._M_type)
413           {
414             __formatter->_M_print_word("type = ");
415             _M_print_field(__formatter, "type");
416             
417             if (_M_variant._M_iterator._M_constness != __unknown_constness)
418               {
419                 __formatter->_M_print_word(" (");
420                 _M_print_field(__formatter, "constness");
421                 __formatter->_M_print_word(" iterator)");
422               }
423             __formatter->_M_print_word(";\n");
424           }
425         
426         if (_M_variant._M_iterator._M_state != __unknown_state)
427           {
428             __formatter->_M_print_word("  state = ");
429             _M_print_field(__formatter, "state");
430             __formatter->_M_print_word(";\n");
431           }
432         
433         if (_M_variant._M_iterator._M_sequence)
434           {
435             __formatter->_M_print_word("  references sequence ");
436             if (_M_variant._M_iterator._M_seq_type)
437               {
438                 __formatter->_M_print_word("with type `");
439                 _M_print_field(__formatter, "seq_type");
440                 __formatter->_M_print_word("' ");
441               }
442             
443             __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p\n", 
444                                         _M_variant._M_sequence._M_address);
445             __formatter->_M_print_word(__buf);
446           }
447         __formatter->_M_print_word("}\n");
448       }
449     else if (_M_kind == __sequence)
450       {
451         __formatter->_M_print_word("sequence ");
452         if (_M_variant._M_sequence._M_name)
453           {
454             __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ", 
455                                         _M_variant._M_sequence._M_name);
456             __formatter->_M_print_word(__buf);
457           }
458         
459         __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n", 
460                                     _M_variant._M_sequence._M_address);
461         __formatter->_M_print_word(__buf);
462         
463         if (_M_variant._M_sequence._M_type)
464           {
465             __formatter->_M_print_word("  type = ");
466             _M_print_field(__formatter, "type");
467             __formatter->_M_print_word(";\n");
468           }       
469         __formatter->_M_print_word("}\n");
470       }
471   }
472
473   const _Error_formatter&
474   _Error_formatter::_M_message(_Debug_msg_id __id) const
475   { return this->_M_message(_S_debug_messages[__id]); }
476   
477   void
478   _Error_formatter::_M_error() const
479   {
480     const int __bufsize = 128;
481     char __buf[__bufsize];
482     
483     // Emit file & line number information
484     _M_column = 1;
485     _M_wordwrap = false;
486     if (_M_file)
487       {
488         _M_format_word(__buf, __bufsize, "%s:", _M_file);
489         _M_print_word(__buf);
490         _M_column += strlen(__buf);
491       }
492     
493     if (_M_line > 0)
494       {
495         _M_format_word(__buf, __bufsize, "%u:", _M_line);
496         _M_print_word(__buf);
497         _M_column += strlen(__buf);
498       }
499     
500     if (_M_max_length)
501       _M_wordwrap = true;
502     _M_print_word("error: ");
503     
504     // Print the error message
505     assert(_M_text);
506     _M_print_string(_M_text);
507     _M_print_word(".\n");
508     
509     // Emit descriptions of the objects involved in the operation
510     _M_wordwrap = false;
511     bool __has_noninteger_parameters = false;
512     for (unsigned int __i = 0; __i < _M_num_parameters; ++__i)
513       {
514         if (_M_parameters[__i]._M_kind == _Parameter::__iterator
515             || _M_parameters[__i]._M_kind == _Parameter::__sequence)
516           {
517             if (!__has_noninteger_parameters)
518               {
519                 _M_first_line = true;
520                 _M_print_word("\nObjects involved in the operation:\n");
521                 __has_noninteger_parameters = true;
522               }
523             _M_parameters[__i]._M_print_description(this);
524           }
525       }
526     
527     abort();
528   }
529
530   template<typename _Tp>
531     void
532     _Error_formatter::_M_format_word(char* __buf, 
533                                      int __n __attribute__ ((__unused__)), 
534                                      const char* __fmt, _Tp __s) const
535     {
536 #ifdef _GLIBCXX_USE_C99
537       std::snprintf(__buf, __n, __fmt, __s);
538 #else
539       std::sprintf(__buf, __fmt, __s);
540 #endif
541     }
542
543   
544   void 
545   _Error_formatter::_M_print_word(const char* __word) const
546   {
547     if (!_M_wordwrap) 
548       {
549         fprintf(stderr, "%s", __word);
550         return;
551       }
552     
553     size_t __length = strlen(__word);
554     if (__length == 0)
555       return;
556     
557     if ((_M_column + __length < _M_max_length)
558         || (__length >= _M_max_length && _M_column == 1)) 
559       {
560         // If this isn't the first line, indent
561         if (_M_column == 1 && !_M_first_line)
562           {
563             char __spacing[_M_indent + 1];
564             for (int i = 0; i < _M_indent; ++i)
565               __spacing[i] = ' ';
566             __spacing[_M_indent] = '\0';
567             fprintf(stderr, "%s", __spacing);
568             _M_column += _M_indent;
569           }
570         
571         fprintf(stderr, "%s", __word);
572         _M_column += __length;
573         
574         if (__word[__length - 1] == '\n') 
575           {
576             _M_first_line = false;
577             _M_column = 1;
578           }
579       }
580     else
581       {
582         _M_column = 1;
583         _M_print_word("\n");
584         _M_print_word(__word);
585       }
586   }
587   
588   void
589   _Error_formatter::
590   _M_print_string(const char* __string) const
591   {
592     const char* __start = __string;
593     const char* __finish = __start;
594     const int __bufsize = 128;
595     char __buf[__bufsize];
596
597     while (*__start)
598       {
599         if (*__start != '%')
600           {
601             // [__start, __finish) denotes the next word
602             __finish = __start;
603             while (isalnum(*__finish))
604               ++__finish;
605             if (__start == __finish)
606               ++__finish;
607             if (isspace(*__finish))
608               ++__finish;
609             
610             const ptrdiff_t __len = __finish - __start;
611             assert(__len < __bufsize);
612             memcpy(__buf, __start, __len);
613             __buf[__len] = '\0';
614             _M_print_word(__buf);
615             __start = __finish;
616             
617             // Skip extra whitespace
618             while (*__start == ' ') 
619               ++__start;
620             
621             continue;
622           } 
623         
624         ++__start;
625         assert(*__start);
626         if (*__start == '%')
627           {
628             _M_print_word("%");
629             ++__start;
630             continue;
631           }
632         
633         // Get the parameter number
634         assert(*__start >= '1' && *__start <= '9');
635         size_t __param = *__start - '0';
636         --__param;
637         assert(__param < _M_num_parameters);
638       
639         // '.' separates the parameter number from the field
640         // name, if there is one.
641         ++__start;
642         if (*__start != '.')
643           {
644             assert(*__start == ';');
645             ++__start;
646             __buf[0] = '\0';
647             if (_M_parameters[__param]._M_kind == _Parameter::__integer)
648               {
649                 _M_format_word(__buf, __bufsize, "%ld", 
650                                _M_parameters[__param]._M_variant._M_integer._M_value);
651                 _M_print_word(__buf);
652               }
653             else if (_M_parameters[__param]._M_kind == _Parameter::__string)
654               _M_print_string(_M_parameters[__param]._M_variant._M_string._M_value);
655             continue;
656           }
657         
658         // Extract the field name we want
659         enum { __max_field_len = 16 };
660         char __field[__max_field_len];
661         int __field_idx = 0;
662         ++__start;
663         while (*__start != ';')
664           {
665             assert(*__start);
666             assert(__field_idx < __max_field_len-1);
667             __field[__field_idx++] = *__start++;
668           }
669         ++__start;
670         __field[__field_idx] = 0;
671         
672         _M_parameters[__param]._M_print_field(this, __field);             
673       }
674   }
675
676   void
677   _Error_formatter::_M_get_max_length() const
678   {
679     const char* __nptr = std::getenv("GLIBCXX_DEBUG_MESSAGE_LENGTH");
680     if (__nptr)
681       {
682         char* __endptr;
683         const unsigned long __ret = std::strtoul(__nptr, &__endptr, 0);
684         if (*__nptr != '\0' && *__endptr == '\0')
685           _M_max_length = __ret;
686       }
687   }
688
689   // Instantiations.
690   template
691     void
692     _Error_formatter::_M_format_word(char*, int, const char*, 
693                                      const void*) const;
694
695   template
696     void
697     _Error_formatter::_M_format_word(char*, int, const char*, long) const;
698
699   template
700     void
701     _Error_formatter::_M_format_word(char*, int, const char*, 
702                                      std::size_t) const;
703
704   template
705     void
706     _Error_formatter::_M_format_word(char*, int, const char*, 
707                                      const char*) const;
708 } // namespace __gnu_debug