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