debug.cc

00001 // Debugging mode support code -*- C++ -*- 00002 00003 // Copyright (C) 2003, 2004 00004 // Free Software Foundation, Inc. 00005 // 00006 // This file is part of the GNU ISO C++ Library. This library is free 00007 // software; you can redistribute it and/or modify it under the 00008 // terms of the GNU General Public License as published by the 00009 // Free Software Foundation; either version 2, or (at your option) 00010 // any later version. 00011 00012 // This library is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 // GNU General Public License for more details. 00016 00017 // You should have received a copy of the GNU General Public License along 00018 // with this library; see the file COPYING. If not, write to the Free 00019 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 00020 // USA. 00021 00022 // As a special exception, you may use this file as part of a free software 00023 // library without restriction. Specifically, if other files instantiate 00024 // templates or use macros or inline functions from this file, or you compile 00025 // this file and link it with other files to produce an executable, this 00026 // file does not by itself cause the resulting executable to be covered by 00027 // the GNU General Public License. This exception does not however 00028 // invalidate any other reasons why the executable file might be covered by 00029 // the GNU General Public License. 00030 00031 #include <debug/debug.h> 00032 #include <debug/safe_sequence.h> 00033 #include <debug/safe_iterator.h> 00034 #include <algorithm> 00035 #include <cstdlib> 00036 #include <cassert> 00037 #include <cstring> 00038 #include <cstdio> 00039 #include <cctype> 00040 00041 using namespace std; 00042 00043 namespace __gnu_debug 00044 { 00045 const char* _S_debug_messages[] = 00046 { 00047 "function requires a valid iterator range [%1.name;, %2.name;)", 00048 "attempt to insert into container with a singular iterator", 00049 "attempt to insert into container with an iterator" 00050 " from a different container", 00051 "attempt to erase from container with a %2.state; iterator", 00052 "attempt to erase from container with an iterator" 00053 " from a different container", 00054 "attempt to subscript container with out-of-bounds index %2;," 00055 " but container only holds %3; elements", 00056 "attempt to access an element in an empty container", 00057 "elements in iterator range [%1.name;, %2.name;)" 00058 " are not partitioned by the value %3;", 00059 "elements in iterator range [%1.name;, %2.name;)" 00060 " are not partitioned by the predicate %3; and value %4;", 00061 "elements in iterator range [%1.name;, %2.name;) are not sorted", 00062 "elements in iterator range [%1.name;, %2.name;)" 00063 " are not sorted according to the predicate %3;", 00064 "elements in iterator range [%1.name;, %2.name;) do not form a heap", 00065 "elements in iterator range [%1.name;, %2.name;)" 00066 " do not form a heap with respect to the predicate %3;", 00067 "attempt to write through a singular bitset reference", 00068 "attempt to read from a singular bitset reference", 00069 "attempt to flip a singular bitset reference", 00070 "attempt to splice a list into itself", 00071 "attempt to splice lists with inequal allocators", 00072 "attempt to splice elements referenced by a %1.state; iterator", 00073 "attempt to splice an iterator from a different container", 00074 "splice destination %1.name;" 00075 " occurs within source range [%2.name;, %3.name;)", 00076 "attempt to initialize an iterator that will immediately become singular", 00077 "attempt to copy-construct an iterator from a singular iterator", 00078 "attempt to construct a constant iterator" 00079 " from a singular mutable iterator", 00080 "attempt to copy from a singular iterator", 00081 "attempt to dereference a %1.state; iterator", 00082 "attempt to increment a %1.state; iterator", 00083 "attempt to decrement a %1.state; iterator", 00084 "attempt to subscript a %1.state; iterator %2; step from" 00085 " its current position, which falls outside its dereferenceable range", 00086 "attempt to advance a %1.state; iterator %2; steps," 00087 " which falls outside its valid range", 00088 "attempt to retreat a %1.state; iterator %2; steps," 00089 " which falls outside its valid range", 00090 "attempt to compare a %1.state; iterator to a %2.state; iterator", 00091 "attempt to compare iterators from different sequences", 00092 "attempt to order a %1.state; iterator to a %2.state; iterator", 00093 "attempt to order iterators from different sequences", 00094 "attempt to compute the difference between a %1.state;" 00095 " iterator to a %2.state; iterator", 00096 "attempt to compute the different between two iterators" 00097 " from different sequences", 00098 "attempt to dereference an end-of-stream istream_iterator", 00099 "attempt to increment an end-of-stream istream_iterator", 00100 "attempt to output via an ostream_iterator with no associated stream", 00101 "attempt to dereference an end-of-stream istreambuf_iterator" 00102 " (this is a GNU extension)", 00103 "attempt to increment an end-of-stream istreambuf_iterator" 00104 }; 00105 00106 void 00107 _Safe_sequence_base:: 00108 _M_detach_all() 00109 { 00110 for (_Safe_iterator_base* __iter = _M_iterators; __iter; ) 00111 { 00112 _Safe_iterator_base* __old = __iter; 00113 __iter = __iter->_M_next; 00114 __old->_M_attach(0, false); 00115 } 00116 00117 for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2; ) 00118 { 00119 _Safe_iterator_base* __old = __iter2; 00120 __iter2 = __iter2->_M_next; 00121 __old->_M_attach(0, true); 00122 } 00123 } 00124 00125 void 00126 _Safe_sequence_base:: 00127 _M_detach_singular() 00128 { 00129 for (_Safe_iterator_base* __iter = _M_iterators; __iter; ) 00130 { 00131 _Safe_iterator_base* __old = __iter; 00132 __iter = __iter->_M_next; 00133 if (__old->_M_singular()) 00134 __old->_M_attach(0, false); 00135 } 00136 00137 for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2; ) 00138 { 00139 _Safe_iterator_base* __old = __iter2; 00140 __iter2 = __iter2->_M_next; 00141 if (__old->_M_singular()) 00142 __old->_M_attach(0, true); 00143 } 00144 } 00145 00146 void 00147 _Safe_sequence_base:: 00148 _M_revalidate_singular() 00149 { 00150 _Safe_iterator_base* __iter; 00151 for (__iter = _M_iterators; __iter; __iter = __iter->_M_next) 00152 { 00153 __iter->_M_version = _M_version; 00154 __iter = __iter->_M_next; 00155 } 00156 00157 for (__iter = _M_const_iterators; __iter; __iter = __iter->_M_next) 00158 { 00159 __iter->_M_version = _M_version; 00160 __iter = __iter->_M_next; 00161 } 00162 } 00163 00164 void 00165 _Safe_sequence_base:: 00166 _M_swap(_Safe_sequence_base& __x) 00167 { 00168 swap(_M_iterators, __x._M_iterators); 00169 swap(_M_const_iterators, __x._M_const_iterators); 00170 swap(_M_version, __x._M_version); 00171 _Safe_iterator_base* __iter; 00172 for (__iter = _M_iterators; __iter; __iter = __iter->_M_next) 00173 __iter->_M_sequence = this; 00174 for (__iter = __x._M_iterators; __iter; __iter = __iter->_M_next) 00175 __iter->_M_sequence = &__x; 00176 for (__iter = _M_const_iterators; __iter; __iter = __iter->_M_next) 00177 __iter->_M_sequence = this; 00178 for (__iter = __x._M_const_iterators; __iter; __iter = __iter->_M_next) 00179 __iter->_M_sequence = &__x; 00180 } 00181 00182 void 00183 _Safe_iterator_base:: 00184 _M_attach(_Safe_sequence_base* __seq, bool __constant) 00185 { 00186 _M_detach(); 00187 00188 // Attach to the new sequence (if there is one) 00189 if (__seq) 00190 { 00191 _M_sequence = __seq; 00192 _M_version = _M_sequence->_M_version; 00193 _M_prior = 0; 00194 if (__constant) 00195 { 00196 _M_next = _M_sequence->_M_const_iterators; 00197 if (_M_next) 00198 _M_next->_M_prior = this; 00199 _M_sequence->_M_const_iterators = this; 00200 } 00201 else 00202 { 00203 _M_next = _M_sequence->_M_iterators; 00204 if (_M_next) 00205 _M_next->_M_prior = this; 00206 _M_sequence->_M_iterators = this; 00207 } 00208 } 00209 } 00210 00211 void 00212 _Safe_iterator_base:: 00213 _M_detach() 00214 { 00215 if (_M_sequence) 00216 { 00217 // Remove us from this sequence's list 00218 if (_M_prior) 00219 _M_prior->_M_next = _M_next; 00220 if (_M_next) 00221 _M_next->_M_prior = _M_prior; 00222 00223 if (_M_sequence->_M_const_iterators == this) 00224 _M_sequence->_M_const_iterators = _M_next; 00225 if (_M_sequence->_M_iterators == this) 00226 _M_sequence->_M_iterators = _M_next; 00227 } 00228 00229 _M_sequence = 0; 00230 _M_version = 0; 00231 _M_prior = 0; 00232 _M_next = 0; 00233 } 00234 00235 bool 00236 _Safe_iterator_base:: 00237 _M_singular() const 00238 { return !_M_sequence || _M_version != _M_sequence->_M_version; } 00239 00240 bool 00241 _Safe_iterator_base:: 00242 _M_can_compare(const _Safe_iterator_base& __x) const 00243 { 00244 return (!_M_singular() && !__x._M_singular() 00245 && _M_sequence == __x._M_sequence); 00246 } 00247 00248 void 00249 _Error_formatter::_Parameter:: 00250 _M_print_field(const _Error_formatter* __formatter, const char* __name) const 00251 { 00252 assert(this->_M_kind != _Parameter::__unused_param); 00253 const int __bufsize = 64; 00254 char __buf[__bufsize]; 00255 00256 if (_M_kind == __iterator) 00257 { 00258 if (strcmp(__name, "name") == 0) 00259 { 00260 assert(_M_variant._M_iterator._M_name); 00261 __formatter->_M_print_word(_M_variant._M_iterator._M_name); 00262 } 00263 else if (strcmp(__name, "address") == 0) 00264 { 00265 __formatter->_M_format_word(__buf, __bufsize, "%p", 00266 _M_variant._M_iterator._M_address); 00267 __formatter->_M_print_word(__buf); 00268 } 00269 else if (strcmp(__name, "type") == 0) 00270 { 00271 assert(_M_variant._M_iterator._M_type); 00272 // TBD: demangle! 00273 __formatter->_M_print_word(_M_variant._M_iterator._M_type->name()); 00274 } 00275 else if (strcmp(__name, "constness") == 0) 00276 { 00277 static const char* __constness_names[__last_constness] = 00278 { 00279 "<unknown>", 00280 "constant", 00281 "mutable" 00282 }; 00283 __formatter->_M_print_word(__constness_names[_M_variant._M_iterator._M_constness]); 00284 } 00285 else if (strcmp(__name, "state") == 0) 00286 { 00287 static const char* __state_names[__last_state] = 00288 { 00289 "<unknown>", 00290 "singular", 00291 "dereferenceable (start-of-sequence)", 00292 "dereferenceable", 00293 "past-the-end" 00294 }; 00295 __formatter->_M_print_word(__state_names[_M_variant._M_iterator._M_state]); 00296 } 00297 else if (strcmp(__name, "sequence") == 0) 00298 { 00299 assert(_M_variant._M_iterator._M_sequence); 00300 __formatter->_M_format_word(__buf, __bufsize, "%p", 00301 _M_variant._M_iterator._M_sequence); 00302 __formatter->_M_print_word(__buf); 00303 } 00304 else if (strcmp(__name, "seq_type") == 0) 00305 { 00306 // TBD: demangle! 00307 assert(_M_variant._M_iterator._M_seq_type); 00308 __formatter->_M_print_word(_M_variant._M_iterator._M_seq_type->name()); 00309 } 00310 else 00311 assert(false); 00312 } 00313 else if (_M_kind == __sequence) 00314 { 00315 if (strcmp(__name, "name") == 0) 00316 { 00317 assert(_M_variant._M_sequence._M_name); 00318 __formatter->_M_print_word(_M_variant._M_sequence._M_name); 00319 } 00320 else if (strcmp(__name, "address") == 0) 00321 { 00322 assert(_M_variant._M_sequence._M_address); 00323 __formatter->_M_format_word(__buf, __bufsize, "%p", 00324 _M_variant._M_sequence._M_address); 00325 __formatter->_M_print_word(__buf); 00326 } 00327 else if (strcmp(__name, "type") == 0) 00328 { 00329 // TBD: demangle! 00330 assert(_M_variant._M_sequence._M_type); 00331 __formatter->_M_print_word(_M_variant._M_sequence._M_type->name()); 00332 } 00333 else 00334 assert(false); 00335 } 00336 else if (_M_kind == __integer) 00337 { 00338 if (strcmp(__name, "name") == 0) 00339 { 00340 assert(_M_variant._M_integer._M_name); 00341 __formatter->_M_print_word(_M_variant._M_integer._M_name); 00342 } 00343 else 00344 assert(false); 00345 } 00346 else if (_M_kind == __string) 00347 { 00348 if (strcmp(__name, "name") == 0) 00349 { 00350 assert(_M_variant._M_string._M_name); 00351 __formatter->_M_print_word(_M_variant._M_string._M_name); 00352 } 00353 else 00354 assert(false); 00355 } 00356 else 00357 { 00358 assert(false); 00359 } 00360 } 00361 00362 void 00363 _Error_formatter::_Parameter:: 00364 _M_print_description(const _Error_formatter* __formatter) const 00365 { 00366 const int __bufsize = 128; 00367 char __buf[__bufsize]; 00368 00369 if (_M_kind == __iterator) 00370 { 00371 __formatter->_M_print_word("iterator "); 00372 if (_M_variant._M_iterator._M_name) 00373 { 00374 __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ", 00375 _M_variant._M_iterator._M_name); 00376 __formatter->_M_print_word(__buf); 00377 } 00378 00379 __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n", 00380 _M_variant._M_iterator._M_address); 00381 __formatter->_M_print_word(__buf); 00382 if (_M_variant._M_iterator._M_type) 00383 { 00384 __formatter->_M_print_word("type = "); 00385 _M_print_field(__formatter, "type"); 00386 00387 if (_M_variant._M_iterator._M_constness != __unknown_constness) 00388 { 00389 __formatter->_M_print_word(" ("); 00390 _M_print_field(__formatter, "constness"); 00391 __formatter->_M_print_word(" iterator)"); 00392 } 00393 __formatter->_M_print_word(";\n"); 00394 } 00395 00396 if (_M_variant._M_iterator._M_state != __unknown_state) 00397 { 00398 __formatter->_M_print_word(" state = "); 00399 _M_print_field(__formatter, "state"); 00400 __formatter->_M_print_word(";\n"); 00401 } 00402 00403 if (_M_variant._M_iterator._M_sequence) 00404 { 00405 __formatter->_M_print_word(" references sequence "); 00406 if (_M_variant._M_iterator._M_seq_type) 00407 { 00408 __formatter->_M_print_word("with type `"); 00409 _M_print_field(__formatter, "seq_type"); 00410 __formatter->_M_print_word("' "); 00411 } 00412 00413 __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p\n", 00414 _M_variant._M_sequence._M_address); 00415 __formatter->_M_print_word(__buf); 00416 } 00417 __formatter->_M_print_word("}\n"); 00418 } 00419 else if (_M_kind == __sequence) 00420 { 00421 __formatter->_M_print_word("sequence "); 00422 if (_M_variant._M_sequence._M_name) 00423 { 00424 __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ", 00425 _M_variant._M_sequence._M_name); 00426 __formatter->_M_print_word(__buf); 00427 } 00428 00429 __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n", 00430 _M_variant._M_sequence._M_address); 00431 __formatter->_M_print_word(__buf); 00432 00433 if (_M_variant._M_sequence._M_type) 00434 { 00435 __formatter->_M_print_word(" type = "); 00436 _M_print_field(__formatter, "type"); 00437 __formatter->_M_print_word(";\n"); 00438 } 00439 __formatter->_M_print_word("}\n"); 00440 } 00441 } 00442 00443 const _Error_formatter& 00444 _Error_formatter::_M_message(_Debug_msg_id __id) const 00445 { return this->_M_message(_S_debug_messages[__id]); } 00446 00447 void 00448 _Error_formatter::_M_error() const 00449 { 00450 const int __bufsize = 128; 00451 char __buf[__bufsize]; 00452 00453 // Emit file & line number information 00454 _M_column = 1; 00455 _M_wordwrap = false; 00456 if (_M_file) 00457 { 00458 _M_format_word(__buf, __bufsize, "%s:", _M_file); 00459 _M_print_word(__buf); 00460 _M_column += strlen(__buf); 00461 } 00462 00463 if (_M_line > 0) 00464 { 00465 _M_format_word(__buf, __bufsize, "%u:", _M_line); 00466 _M_print_word(__buf); 00467 _M_column += strlen(__buf); 00468 } 00469 00470 _M_wordwrap = true; 00471 _M_print_word("error: "); 00472 00473 // Print the error message 00474 assert(_M_text); 00475 _M_print_string(_M_text); 00476 _M_print_word(".\n"); 00477 00478 // Emit descriptions of the objects involved in the operation 00479 _M_wordwrap = false; 00480 bool __has_noninteger_parameters = false; 00481 for (unsigned int __i = 0; __i < _M_num_parameters; ++__i) 00482 { 00483 if (_M_parameters[__i]._M_kind == _Parameter::__iterator 00484 || _M_parameters[__i]._M_kind == _Parameter::__sequence) 00485 { 00486 if (!__has_noninteger_parameters) 00487 { 00488 _M_first_line = true; 00489 _M_print_word("\nObjects involved in the operation:\n"); 00490 __has_noninteger_parameters = true; 00491 } 00492 _M_parameters[__i]._M_print_description(this); 00493 } 00494 } 00495 00496 abort(); 00497 } 00498 00499 template<typename _Tp> 00500 void 00501 _Error_formatter::_M_format_word(char* __buf, 00502 int __n __attribute__((__unused__)), 00503 const char* __fmt, _Tp __s) const 00504 { 00505 #ifdef _GLIBCXX_USE_C99 00506 std::snprintf(__buf, __n, __fmt, __s); 00507 #else 00508 std::sprintf(__buf, __fmt, __s); 00509 #endif 00510 } 00511 00512 00513 void 00514 _Error_formatter::_M_print_word(const char* __word) const 00515 { 00516 if (!_M_wordwrap) 00517 { 00518 fprintf(stderr, "%s", __word); 00519 return; 00520 } 00521 00522 size_t __length = strlen(__word); 00523 if (__length == 0) 00524 return; 00525 00526 if ((_M_column + __length < _M_max_length) 00527 || (__length >= _M_max_length && _M_column == 1)) 00528 { 00529 // If this isn't the first line, indent 00530 if (_M_column == 1 && !_M_first_line) 00531 { 00532 char __spacing[_M_indent + 1]; 00533 for (int i = 0; i < _M_indent; ++i) 00534 __spacing[i] = ' '; 00535 __spacing[_M_indent] = '\0'; 00536 fprintf(stderr, "%s", __spacing); 00537 _M_column += _M_indent; 00538 } 00539 00540 fprintf(stderr, "%s", __word); 00541 _M_column += __length; 00542 00543 if (__word[__length - 1] == '\n') 00544 { 00545 _M_first_line = false; 00546 _M_column = 1; 00547 } 00548 } 00549 else 00550 { 00551 _M_column = 1; 00552 _M_print_word("\n"); 00553 _M_print_word(__word); 00554 } 00555 } 00556 00557 void 00558 _Error_formatter:: 00559 _M_print_string(const char* __string) const 00560 { 00561 const char* __start = __string; 00562 const char* __end = __start; 00563 const int __bufsize = 128; 00564 char __buf[__bufsize]; 00565 00566 while (*__start) 00567 { 00568 if (*__start != '%') 00569 { 00570 // [__start, __end) denotes the next word 00571 __end = __start; 00572 while (isalnum(*__end)) 00573 ++__end; 00574 if (__start == __end) 00575 ++__end; 00576 if (isspace(*__end)) 00577 ++__end; 00578 00579 const ptrdiff_t __len = __end - __start; 00580 assert(__len < __bufsize); 00581 memcpy(__buf, __start, __len); 00582 __buf[__len] = '\0'; 00583 _M_print_word(__buf); 00584 __start = __end; 00585 00586 // Skip extra whitespace 00587 while (*__start == ' ') 00588 ++__start; 00589 00590 continue; 00591 } 00592 00593 ++__start; 00594 assert(*__start); 00595 if (*__start == '%') 00596 { 00597 _M_print_word("%"); 00598 ++__start; 00599 continue; 00600 } 00601 00602 // Get the parameter number 00603 assert(*__start >= '1' && *__start <= '9'); 00604 size_t __param = *__start - '0'; 00605 --__param; 00606 assert(__param < _M_num_parameters); 00607 00608 // '.' separates the parameter number from the field 00609 // name, if there is one. 00610 ++__start; 00611 if (*__start != '.') 00612 { 00613 assert(*__start == ';'); 00614 ++__start; 00615 __buf[0] = '\0'; 00616 if (_M_parameters[__param]._M_kind == _Parameter::__integer) 00617 { 00618 _M_format_word(__buf, __bufsize, "%ld", 00619 _M_parameters[__param]._M_variant._M_integer._M_value); 00620 _M_print_word(__buf); 00621 } 00622 else if (_M_parameters[__param]._M_kind == _Parameter::__string) 00623 _M_print_string(_M_parameters[__param]._M_variant._M_string._M_value); 00624 continue; 00625 } 00626 00627 // Extract the field name we want 00628 enum { __max_field_len = 16 }; 00629 char __field[__max_field_len]; 00630 int __field_idx = 0; 00631 ++__start; 00632 while (*__start != ';') 00633 { 00634 assert(*__start); 00635 assert(__field_idx < __max_field_len-1); 00636 __field[__field_idx++] = *__start++; 00637 } 00638 ++__start; 00639 __field[__field_idx] = 0; 00640 00641 _M_parameters[__param]._M_print_field(this, __field); 00642 } 00643 } 00644 00645 // Instantiations. 00646 template 00647 void 00648 _Error_formatter::_M_format_word(char* __buf, int __n, const char* __fmt, 00649 const void* __s) const; 00650 00651 template 00652 void 00653 _Error_formatter::_M_format_word(char* __buf, int __n, const char* __fmt, 00654 long __s) const; 00655 00656 template 00657 void 00658 _Error_formatter::_M_format_word(char* __buf, int __n, const char* __fmt, 00659 std::size_t __s) const; 00660 00661 template 00662 void 00663 _Error_formatter::_M_format_word(char* __buf, int __n, const char* __fmt, 00664 const char* __s) const; 00665 } // namespace __gnu_debug

Generated on Tue Sep 7 10:05:02 2004 for libstdc++-v3 Source by doxygen 1.3.8