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