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