debug.cc revision 132720
1132720Skan// Debugging mode support code -*- C++ -*- 2132720Skan 3132720Skan// Copyright (C) 2003, 2004 4132720Skan// Free Software Foundation, Inc. 5132720Skan// 6132720Skan// This file is part of the GNU ISO C++ Library. This library is free 7132720Skan// software; you can redistribute it and/or modify it under the 8132720Skan// terms of the GNU General Public License as published by the 9132720Skan// Free Software Foundation; either version 2, or (at your option) 10132720Skan// any later version. 11132720Skan 12132720Skan// This library is distributed in the hope that it will be useful, 13132720Skan// but WITHOUT ANY WARRANTY; without even the implied warranty of 14132720Skan// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15132720Skan// GNU General Public License for more details. 16132720Skan 17132720Skan// You should have received a copy of the GNU General Public License along 18132720Skan// with this library; see the file COPYING. If not, write to the Free 19132720Skan// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 20132720Skan// USA. 21132720Skan 22132720Skan// As a special exception, you may use this file as part of a free software 23132720Skan// library without restriction. Specifically, if other files instantiate 24132720Skan// templates or use macros or inline functions from this file, or you compile 25132720Skan// this file and link it with other files to produce an executable, this 26132720Skan// file does not by itself cause the resulting executable to be covered by 27132720Skan// the GNU General Public License. This exception does not however 28132720Skan// invalidate any other reasons why the executable file might be covered by 29132720Skan// the GNU General Public License. 30132720Skan 31132720Skan#include <debug/debug.h> 32132720Skan#include <debug/safe_sequence.h> 33132720Skan#include <debug/safe_iterator.h> 34132720Skan#include <algorithm> 35132720Skan#include <cstdlib> 36132720Skan#include <cassert> 37132720Skan#include <cstring> 38132720Skan#include <cstdio> 39132720Skan#include <cctype> 40132720Skan 41132720Skanusing namespace std; 42132720Skan 43132720Skannamespace __gnu_debug 44132720Skan{ 45132720Skan const char* _S_debug_messages[] = 46132720Skan { 47132720Skan "function requires a valid iterator range [%1.name;, %2.name;)", 48132720Skan "attempt to insert into container with a singular iterator", 49132720Skan "attempt to insert into container with an iterator" 50132720Skan " from a different container", 51132720Skan "attempt to erase from container with a %2.state; iterator", 52132720Skan "attempt to erase from container with an iterator" 53132720Skan " from a different container", 54132720Skan "attempt to subscript container with out-of-bounds index %2;," 55132720Skan " but container only holds %3; elements", 56132720Skan "attempt to access an element in an empty container", 57132720Skan "elements in iterator range [%1.name;, %2.name;)" 58132720Skan " are not partitioned by the value %3;", 59132720Skan "elements in iterator range [%1.name;, %2.name;)" 60132720Skan " are not partitioned by the predicate %3; and value %4;", 61132720Skan "elements in iterator range [%1.name;, %2.name;) are not sorted", 62132720Skan "elements in iterator range [%1.name;, %2.name;)" 63132720Skan " are not sorted according to the predicate %3;", 64132720Skan "elements in iterator range [%1.name;, %2.name;) do not form a heap", 65132720Skan "elements in iterator range [%1.name;, %2.name;)" 66132720Skan " do not form a heap with respect to the predicate %3;", 67132720Skan "attempt to write through a singular bitset reference", 68132720Skan "attempt to read from a singular bitset reference", 69132720Skan "attempt to flip a singular bitset reference", 70132720Skan "attempt to splice a list into itself", 71132720Skan "attempt to splice lists with inequal allocators", 72132720Skan "attempt to splice elements referenced by a %1.state; iterator", 73132720Skan "attempt to splice an iterator from a different container", 74132720Skan "splice destination %1.name;" 75132720Skan " occurs within source range [%2.name;, %3.name;)", 76132720Skan "attempt to initialize an iterator that will immediately become singular", 77132720Skan "attempt to copy-construct an iterator from a singular iterator", 78132720Skan "attempt to construct a constant iterator" 79132720Skan " from a singular mutable iterator", 80132720Skan "attempt to copy from a singular iterator", 81132720Skan "attempt to dereference a %1.state; iterator", 82132720Skan "attempt to increment a %1.state; iterator", 83132720Skan "attempt to decrement a %1.state; iterator", 84132720Skan "attempt to subscript a %1.state; iterator %2; step from" 85132720Skan " its current position, which falls outside its dereferenceable range", 86132720Skan "attempt to advance a %1.state; iterator %2; steps," 87132720Skan " which falls outside its valid range", 88132720Skan "attempt to retreat a %1.state; iterator %2; steps," 89132720Skan " which falls outside its valid range", 90132720Skan "attempt to compare a %1.state; iterator to a %2.state; iterator", 91132720Skan "attempt to compare iterators from different sequences", 92132720Skan "attempt to order a %1.state; iterator to a %2.state; iterator", 93132720Skan "attempt to order iterators from different sequences", 94132720Skan "attempt to compute the difference between a %1.state;" 95132720Skan " iterator to a %2.state; iterator", 96132720Skan "attempt to compute the different between two iterators" 97132720Skan " from different sequences", 98132720Skan "attempt to dereference an end-of-stream istream_iterator", 99132720Skan "attempt to increment an end-of-stream istream_iterator", 100132720Skan "attempt to output via an ostream_iterator with no associated stream", 101132720Skan "attempt to dereference an end-of-stream istreambuf_iterator" 102132720Skan " (this is a GNU extension)", 103132720Skan "attempt to increment an end-of-stream istreambuf_iterator" 104132720Skan }; 105132720Skan 106132720Skan void 107132720Skan _Safe_sequence_base:: 108132720Skan _M_detach_all() 109132720Skan { 110132720Skan for (_Safe_iterator_base* __iter = _M_iterators; __iter; ) 111132720Skan { 112132720Skan _Safe_iterator_base* __old = __iter; 113132720Skan __iter = __iter->_M_next; 114132720Skan __old->_M_attach(0, false); 115132720Skan } 116132720Skan 117132720Skan for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2; ) 118132720Skan { 119132720Skan _Safe_iterator_base* __old = __iter2; 120132720Skan __iter2 = __iter2->_M_next; 121132720Skan __old->_M_attach(0, true); 122132720Skan } 123132720Skan } 124132720Skan 125132720Skan void 126132720Skan _Safe_sequence_base:: 127132720Skan _M_detach_singular() 128132720Skan { 129132720Skan for (_Safe_iterator_base* __iter = _M_iterators; __iter; ) 130132720Skan { 131132720Skan _Safe_iterator_base* __old = __iter; 132132720Skan __iter = __iter->_M_next; 133132720Skan if (__old->_M_singular()) 134132720Skan __old->_M_attach(0, false); 135132720Skan } 136132720Skan 137132720Skan for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2; ) 138132720Skan { 139132720Skan _Safe_iterator_base* __old = __iter2; 140132720Skan __iter2 = __iter2->_M_next; 141132720Skan if (__old->_M_singular()) 142132720Skan __old->_M_attach(0, true); 143132720Skan } 144132720Skan } 145132720Skan 146132720Skan void 147132720Skan _Safe_sequence_base:: 148132720Skan _M_revalidate_singular() 149132720Skan { 150132720Skan _Safe_iterator_base* __iter; 151132720Skan for (__iter = _M_iterators; __iter; __iter = __iter->_M_next) 152132720Skan { 153132720Skan __iter->_M_version = _M_version; 154132720Skan __iter = __iter->_M_next; 155132720Skan } 156132720Skan 157132720Skan for (__iter = _M_const_iterators; __iter; __iter = __iter->_M_next) 158132720Skan { 159132720Skan __iter->_M_version = _M_version; 160132720Skan __iter = __iter->_M_next; 161132720Skan } 162132720Skan } 163132720Skan 164132720Skan void 165132720Skan _Safe_sequence_base:: 166132720Skan _M_swap(_Safe_sequence_base& __x) 167132720Skan { 168132720Skan swap(_M_iterators, __x._M_iterators); 169132720Skan swap(_M_const_iterators, __x._M_const_iterators); 170132720Skan swap(_M_version, __x._M_version); 171132720Skan _Safe_iterator_base* __iter; 172132720Skan for (__iter = _M_iterators; __iter; __iter = __iter->_M_next) 173132720Skan __iter->_M_sequence = this; 174132720Skan for (__iter = __x._M_iterators; __iter; __iter = __iter->_M_next) 175132720Skan __iter->_M_sequence = &__x; 176132720Skan for (__iter = _M_const_iterators; __iter; __iter = __iter->_M_next) 177132720Skan __iter->_M_sequence = this; 178132720Skan for (__iter = __x._M_const_iterators; __iter; __iter = __iter->_M_next) 179132720Skan __iter->_M_sequence = &__x; 180132720Skan } 181132720Skan 182132720Skan void 183132720Skan _Safe_iterator_base:: 184132720Skan _M_attach(_Safe_sequence_base* __seq, bool __constant) 185132720Skan { 186132720Skan _M_detach(); 187132720Skan 188132720Skan // Attach to the new sequence (if there is one) 189132720Skan if (__seq) 190132720Skan { 191132720Skan _M_sequence = __seq; 192132720Skan _M_version = _M_sequence->_M_version; 193132720Skan _M_prior = 0; 194132720Skan if (__constant) 195132720Skan { 196132720Skan _M_next = _M_sequence->_M_const_iterators; 197132720Skan if (_M_next) 198132720Skan _M_next->_M_prior = this; 199132720Skan _M_sequence->_M_const_iterators = this; 200132720Skan } 201132720Skan else 202132720Skan { 203132720Skan _M_next = _M_sequence->_M_iterators; 204132720Skan if (_M_next) 205132720Skan _M_next->_M_prior = this; 206132720Skan _M_sequence->_M_iterators = this; 207132720Skan } 208132720Skan } 209132720Skan } 210132720Skan 211132720Skan void 212132720Skan _Safe_iterator_base:: 213132720Skan _M_detach() 214132720Skan { 215132720Skan if (_M_sequence) 216132720Skan { 217132720Skan // Remove us from this sequence's list 218132720Skan if (_M_prior) 219132720Skan _M_prior->_M_next = _M_next; 220132720Skan if (_M_next) 221132720Skan _M_next->_M_prior = _M_prior; 222132720Skan 223132720Skan if (_M_sequence->_M_const_iterators == this) 224132720Skan _M_sequence->_M_const_iterators = _M_next; 225132720Skan if (_M_sequence->_M_iterators == this) 226132720Skan _M_sequence->_M_iterators = _M_next; 227132720Skan } 228132720Skan 229132720Skan _M_sequence = 0; 230132720Skan _M_version = 0; 231132720Skan _M_prior = 0; 232132720Skan _M_next = 0; 233132720Skan } 234132720Skan 235132720Skan bool 236132720Skan _Safe_iterator_base:: 237132720Skan _M_singular() const 238132720Skan { return !_M_sequence || _M_version != _M_sequence->_M_version; } 239132720Skan 240132720Skan bool 241132720Skan _Safe_iterator_base:: 242132720Skan _M_can_compare(const _Safe_iterator_base& __x) const 243132720Skan { 244132720Skan return (!_M_singular() && !__x._M_singular() 245132720Skan && _M_sequence == __x._M_sequence); 246132720Skan } 247132720Skan 248132720Skan void 249132720Skan _Error_formatter::_Parameter:: 250132720Skan _M_print_field(const _Error_formatter* __formatter, const char* __name) const 251132720Skan { 252132720Skan assert(this->_M_kind != _Parameter::__unused_param); 253132720Skan const int __bufsize = 64; 254132720Skan char __buf[__bufsize]; 255132720Skan 256132720Skan if (_M_kind == __iterator) 257132720Skan { 258132720Skan if (strcmp(__name, "name") == 0) 259132720Skan { 260132720Skan assert(_M_variant._M_iterator._M_name); 261132720Skan __formatter->_M_print_word(_M_variant._M_iterator._M_name); 262132720Skan } 263132720Skan else if (strcmp(__name, "address") == 0) 264132720Skan { 265132720Skan __formatter->_M_format_word(__buf, __bufsize, "%p", 266132720Skan _M_variant._M_iterator._M_address); 267132720Skan __formatter->_M_print_word(__buf); 268132720Skan } 269132720Skan else if (strcmp(__name, "type") == 0) 270132720Skan { 271132720Skan assert(_M_variant._M_iterator._M_type); 272132720Skan // TBD: demangle! 273132720Skan __formatter->_M_print_word(_M_variant._M_iterator._M_type->name()); 274132720Skan } 275132720Skan else if (strcmp(__name, "constness") == 0) 276132720Skan { 277132720Skan static const char* __constness_names[__last_constness] = 278132720Skan { 279132720Skan "<unknown>", 280132720Skan "constant", 281132720Skan "mutable" 282132720Skan }; 283132720Skan __formatter->_M_print_word(__constness_names[_M_variant._M_iterator._M_constness]); 284132720Skan } 285132720Skan else if (strcmp(__name, "state") == 0) 286132720Skan { 287132720Skan static const char* __state_names[__last_state] = 288132720Skan { 289132720Skan "<unknown>", 290132720Skan "singular", 291132720Skan "dereferenceable (start-of-sequence)", 292132720Skan "dereferenceable", 293132720Skan "past-the-end" 294132720Skan }; 295132720Skan __formatter->_M_print_word(__state_names[_M_variant._M_iterator._M_state]); 296132720Skan } 297132720Skan else if (strcmp(__name, "sequence") == 0) 298132720Skan { 299132720Skan assert(_M_variant._M_iterator._M_sequence); 300132720Skan __formatter->_M_format_word(__buf, __bufsize, "%p", 301132720Skan _M_variant._M_iterator._M_sequence); 302132720Skan __formatter->_M_print_word(__buf); 303132720Skan } 304132720Skan else if (strcmp(__name, "seq_type") == 0) 305132720Skan { 306132720Skan // TBD: demangle! 307132720Skan assert(_M_variant._M_iterator._M_seq_type); 308132720Skan __formatter->_M_print_word(_M_variant._M_iterator._M_seq_type->name()); 309132720Skan } 310132720Skan else 311132720Skan assert(false); 312132720Skan } 313132720Skan else if (_M_kind == __sequence) 314132720Skan { 315132720Skan if (strcmp(__name, "name") == 0) 316132720Skan { 317132720Skan assert(_M_variant._M_sequence._M_name); 318132720Skan __formatter->_M_print_word(_M_variant._M_sequence._M_name); 319132720Skan } 320132720Skan else if (strcmp(__name, "address") == 0) 321132720Skan { 322132720Skan assert(_M_variant._M_sequence._M_address); 323132720Skan __formatter->_M_format_word(__buf, __bufsize, "%p", 324132720Skan _M_variant._M_sequence._M_address); 325132720Skan __formatter->_M_print_word(__buf); 326132720Skan } 327132720Skan else if (strcmp(__name, "type") == 0) 328132720Skan { 329132720Skan // TBD: demangle! 330132720Skan assert(_M_variant._M_sequence._M_type); 331132720Skan __formatter->_M_print_word(_M_variant._M_sequence._M_type->name()); 332132720Skan } 333132720Skan else 334132720Skan assert(false); 335132720Skan } 336132720Skan else if (_M_kind == __integer) 337132720Skan { 338132720Skan if (strcmp(__name, "name") == 0) 339132720Skan { 340132720Skan assert(_M_variant._M_integer._M_name); 341132720Skan __formatter->_M_print_word(_M_variant._M_integer._M_name); 342132720Skan } 343132720Skan else 344132720Skan assert(false); 345132720Skan } 346132720Skan else if (_M_kind == __string) 347132720Skan { 348132720Skan if (strcmp(__name, "name") == 0) 349132720Skan { 350132720Skan assert(_M_variant._M_string._M_name); 351132720Skan __formatter->_M_print_word(_M_variant._M_string._M_name); 352132720Skan } 353132720Skan else 354132720Skan assert(false); 355132720Skan } 356132720Skan else 357132720Skan { 358132720Skan assert(false); 359132720Skan } 360132720Skan } 361132720Skan 362132720Skan void 363132720Skan _Error_formatter::_Parameter:: 364132720Skan _M_print_description(const _Error_formatter* __formatter) const 365132720Skan { 366132720Skan const int __bufsize = 128; 367132720Skan char __buf[__bufsize]; 368132720Skan 369132720Skan if (_M_kind == __iterator) 370132720Skan { 371132720Skan __formatter->_M_print_word("iterator "); 372132720Skan if (_M_variant._M_iterator._M_name) 373132720Skan { 374132720Skan __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ", 375132720Skan _M_variant._M_iterator._M_name); 376132720Skan __formatter->_M_print_word(__buf); 377132720Skan } 378132720Skan 379132720Skan __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n", 380132720Skan _M_variant._M_iterator._M_address); 381132720Skan __formatter->_M_print_word(__buf); 382132720Skan if (_M_variant._M_iterator._M_type) 383132720Skan { 384132720Skan __formatter->_M_print_word("type = "); 385132720Skan _M_print_field(__formatter, "type"); 386132720Skan 387132720Skan if (_M_variant._M_iterator._M_constness != __unknown_constness) 388132720Skan { 389132720Skan __formatter->_M_print_word(" ("); 390132720Skan _M_print_field(__formatter, "constness"); 391132720Skan __formatter->_M_print_word(" iterator)"); 392132720Skan } 393132720Skan __formatter->_M_print_word(";\n"); 394132720Skan } 395132720Skan 396132720Skan if (_M_variant._M_iterator._M_state != __unknown_state) 397132720Skan { 398132720Skan __formatter->_M_print_word(" state = "); 399132720Skan _M_print_field(__formatter, "state"); 400132720Skan __formatter->_M_print_word(";\n"); 401132720Skan } 402132720Skan 403132720Skan if (_M_variant._M_iterator._M_sequence) 404132720Skan { 405132720Skan __formatter->_M_print_word(" references sequence "); 406132720Skan if (_M_variant._M_iterator._M_seq_type) 407132720Skan { 408132720Skan __formatter->_M_print_word("with type `"); 409132720Skan _M_print_field(__formatter, "seq_type"); 410132720Skan __formatter->_M_print_word("' "); 411132720Skan } 412132720Skan 413132720Skan __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p\n", 414132720Skan _M_variant._M_sequence._M_address); 415132720Skan __formatter->_M_print_word(__buf); 416132720Skan } 417132720Skan __formatter->_M_print_word("}\n"); 418132720Skan } 419132720Skan else if (_M_kind == __sequence) 420132720Skan { 421132720Skan __formatter->_M_print_word("sequence "); 422132720Skan if (_M_variant._M_sequence._M_name) 423132720Skan { 424132720Skan __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ", 425132720Skan _M_variant._M_sequence._M_name); 426132720Skan __formatter->_M_print_word(__buf); 427132720Skan } 428132720Skan 429132720Skan __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n", 430132720Skan _M_variant._M_sequence._M_address); 431132720Skan __formatter->_M_print_word(__buf); 432132720Skan 433132720Skan if (_M_variant._M_sequence._M_type) 434132720Skan { 435132720Skan __formatter->_M_print_word(" type = "); 436132720Skan _M_print_field(__formatter, "type"); 437132720Skan __formatter->_M_print_word(";\n"); 438132720Skan } 439132720Skan __formatter->_M_print_word("}\n"); 440132720Skan } 441132720Skan } 442132720Skan 443132720Skan const _Error_formatter& 444132720Skan _Error_formatter::_M_message(_Debug_msg_id __id) const 445132720Skan { return this->_M_message(_S_debug_messages[__id]); } 446132720Skan 447132720Skan void 448132720Skan _Error_formatter::_M_error() const 449132720Skan { 450132720Skan const int __bufsize = 128; 451132720Skan char __buf[__bufsize]; 452132720Skan 453132720Skan // Emit file & line number information 454132720Skan _M_column = 1; 455132720Skan _M_wordwrap = false; 456132720Skan if (_M_file) 457132720Skan { 458132720Skan _M_format_word(__buf, __bufsize, "%s:", _M_file); 459132720Skan _M_print_word(__buf); 460132720Skan _M_column += strlen(__buf); 461132720Skan } 462132720Skan 463132720Skan if (_M_line > 0) 464132720Skan { 465132720Skan _M_format_word(__buf, __bufsize, "%u:", _M_line); 466132720Skan _M_print_word(__buf); 467132720Skan _M_column += strlen(__buf); 468132720Skan } 469132720Skan 470132720Skan _M_wordwrap = true; 471132720Skan _M_print_word("error: "); 472132720Skan 473132720Skan // Print the error message 474132720Skan assert(_M_text); 475132720Skan _M_print_string(_M_text); 476132720Skan _M_print_word(".\n"); 477132720Skan 478132720Skan // Emit descriptions of the objects involved in the operation 479132720Skan _M_wordwrap = false; 480132720Skan bool __has_noninteger_parameters = false; 481132720Skan for (unsigned int __i = 0; __i < _M_num_parameters; ++__i) 482132720Skan { 483132720Skan if (_M_parameters[__i]._M_kind == _Parameter::__iterator 484132720Skan || _M_parameters[__i]._M_kind == _Parameter::__sequence) 485132720Skan { 486132720Skan if (!__has_noninteger_parameters) 487132720Skan { 488132720Skan _M_first_line = true; 489132720Skan _M_print_word("\nObjects involved in the operation:\n"); 490132720Skan __has_noninteger_parameters = true; 491132720Skan } 492132720Skan _M_parameters[__i]._M_print_description(this); 493132720Skan } 494132720Skan } 495132720Skan 496132720Skan abort(); 497132720Skan } 498132720Skan 499132720Skan template<typename _Tp> 500132720Skan void 501132720Skan _Error_formatter::_M_format_word(char* __buf, 502132720Skan int __n __attribute__((__unused__)), 503132720Skan const char* __fmt, _Tp __s) const 504132720Skan { 505132720Skan#ifdef _GLIBCXX_USE_C99 506132720Skan std::snprintf(__buf, __n, __fmt, __s); 507132720Skan#else 508132720Skan std::sprintf(__buf, __fmt, __s); 509132720Skan#endif 510132720Skan } 511132720Skan 512132720Skan 513132720Skan void 514132720Skan _Error_formatter::_M_print_word(const char* __word) const 515132720Skan { 516132720Skan if (!_M_wordwrap) 517132720Skan { 518132720Skan fprintf(stderr, "%s", __word); 519132720Skan return; 520132720Skan } 521132720Skan 522132720Skan size_t __length = strlen(__word); 523132720Skan if (__length == 0) 524132720Skan return; 525132720Skan 526132720Skan if ((_M_column + __length < _M_max_length) 527132720Skan || (__length >= _M_max_length && _M_column == 1)) 528132720Skan { 529132720Skan // If this isn't the first line, indent 530132720Skan if (_M_column == 1 && !_M_first_line) 531132720Skan { 532132720Skan char __spacing[_M_indent + 1]; 533132720Skan for (int i = 0; i < _M_indent; ++i) 534132720Skan __spacing[i] = ' '; 535132720Skan __spacing[_M_indent] = '\0'; 536132720Skan fprintf(stderr, "%s", __spacing); 537132720Skan _M_column += _M_indent; 538132720Skan } 539132720Skan 540132720Skan fprintf(stderr, "%s", __word); 541132720Skan _M_column += __length; 542132720Skan 543132720Skan if (__word[__length - 1] == '\n') 544132720Skan { 545132720Skan _M_first_line = false; 546132720Skan _M_column = 1; 547132720Skan } 548132720Skan } 549132720Skan else 550132720Skan { 551132720Skan _M_column = 1; 552132720Skan _M_print_word("\n"); 553132720Skan _M_print_word(__word); 554132720Skan } 555132720Skan } 556132720Skan 557132720Skan void 558132720Skan _Error_formatter:: 559132720Skan _M_print_string(const char* __string) const 560132720Skan { 561132720Skan const char* __start = __string; 562132720Skan const char* __end = __start; 563132720Skan const int __bufsize = 128; 564132720Skan char __buf[__bufsize]; 565132720Skan 566132720Skan while (*__start) 567132720Skan { 568132720Skan if (*__start != '%') 569132720Skan { 570132720Skan // [__start, __end) denotes the next word 571132720Skan __end = __start; 572132720Skan while (isalnum(*__end)) ++__end; 573132720Skan if (__start == __end) ++__end; 574132720Skan if (isspace(*__end)) ++__end; 575132720Skan 576132720Skan assert(__end - __start + 1< __bufsize); 577132720Skan _M_format_word(__buf, __end - __start + 1, "%s", __start); 578132720Skan _M_print_word(__buf); 579132720Skan __start = __end; 580132720Skan 581132720Skan // Skip extra whitespace 582132720Skan while (*__start == ' ') 583132720Skan ++__start; 584132720Skan 585132720Skan continue; 586132720Skan } 587132720Skan 588132720Skan ++__start; 589132720Skan assert(*__start); 590132720Skan if (*__start == '%') 591132720Skan { 592132720Skan _M_print_word("%"); 593132720Skan ++__start; 594132720Skan continue; 595132720Skan } 596132720Skan 597132720Skan // Get the parameter number 598132720Skan assert(*__start >= '1' && *__start <= '9'); 599132720Skan size_t __param = *__start - '0'; 600132720Skan --__param; 601132720Skan assert(__param < _M_num_parameters); 602132720Skan 603132720Skan // '.' separates the parameter number from the field 604132720Skan // name, if there is one. 605132720Skan ++__start; 606132720Skan if (*__start != '.') 607132720Skan { 608132720Skan assert(*__start == ';'); 609132720Skan ++__start; 610132720Skan __buf[0] = '\0'; 611132720Skan if (_M_parameters[__param]._M_kind == _Parameter::__integer) 612132720Skan { 613132720Skan _M_format_word(__buf, __bufsize, "%ld", 614132720Skan _M_parameters[__param]._M_variant._M_integer._M_value); 615132720Skan _M_print_word(__buf); 616132720Skan } 617132720Skan else if (_M_parameters[__param]._M_kind == _Parameter::__string) 618132720Skan _M_print_string(_M_parameters[__param]._M_variant._M_string._M_value); 619132720Skan continue; 620132720Skan } 621132720Skan 622132720Skan // Extract the field name we want 623132720Skan enum { __max_field_len = 16 }; 624132720Skan char __field[__max_field_len]; 625132720Skan int __field_idx = 0; 626132720Skan ++__start; 627132720Skan while (*__start != ';') 628132720Skan { 629132720Skan assert(*__start); 630132720Skan assert(__field_idx < __max_field_len-1); 631132720Skan __field[__field_idx++] = *__start++; 632132720Skan } 633132720Skan ++__start; 634132720Skan __field[__field_idx] = 0; 635132720Skan 636132720Skan _M_parameters[__param]._M_print_field(this, __field); 637132720Skan } 638132720Skan } 639132720Skan 640132720Skan // Instantiations. 641132720Skan template 642132720Skan void 643132720Skan _Error_formatter::_M_format_word(char* __buf, int __n, const char* __fmt, 644132720Skan const void* __s) const; 645132720Skan 646132720Skan template 647132720Skan void 648132720Skan _Error_formatter::_M_format_word(char* __buf, int __n, const char* __fmt, 649132720Skan long __s) const; 650132720Skan 651132720Skan template 652132720Skan void 653132720Skan _Error_formatter::_M_format_word(char* __buf, int __n, const char* __fmt, 654132720Skan std::size_t __s) const; 655132720Skan 656132720Skan template 657132720Skan void 658132720Skan _Error_formatter::_M_format_word(char* __buf, int __n, const char* __fmt, 659132720Skan const char* __s) const; 660132720Skan} // namespace __gnu_debug 661