1*404b540aSrobert // Debug-mode error formatting implementation -*- C++ -*- 2*404b540aSrobert 3*404b540aSrobert // Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. 4*404b540aSrobert // 5*404b540aSrobert // This file is part of the GNU ISO C++ Library. This library is free 6*404b540aSrobert // software; you can redistribute it and/or modify it under the 7*404b540aSrobert // terms of the GNU General Public License as published by the 8*404b540aSrobert // Free Software Foundation; either version 2, or (at your option) 9*404b540aSrobert // any later version. 10*404b540aSrobert 11*404b540aSrobert // This library is distributed in the hope that it will be useful, 12*404b540aSrobert // but WITHOUT ANY WARRANTY; without even the implied warranty of 13*404b540aSrobert // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*404b540aSrobert // GNU General Public License for more details. 15*404b540aSrobert 16*404b540aSrobert // You should have received a copy of the GNU General Public License along 17*404b540aSrobert // with this library; see the file COPYING. If not, write to the Free 18*404b540aSrobert // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 19*404b540aSrobert // USA. 20*404b540aSrobert 21*404b540aSrobert // As a special exception, you may use this file as part of a free software 22*404b540aSrobert // library without restriction. Specifically, if other files instantiate 23*404b540aSrobert // templates or use macros or inline functions from this file, or you compile 24*404b540aSrobert // this file and link it with other files to produce an executable, this 25*404b540aSrobert // file does not by itself cause the resulting executable to be covered by 26*404b540aSrobert // the GNU General Public License. This exception does not however 27*404b540aSrobert // invalidate any other reasons why the executable file might be covered by 28*404b540aSrobert // the GNU General Public License. 29*404b540aSrobert 30*404b540aSrobert /** @file debug/formatter.h 31*404b540aSrobert * This file is a GNU debug extension to the Standard C++ Library. 32*404b540aSrobert */ 33*404b540aSrobert 34*404b540aSrobert #ifndef _GLIBCXX_DEBUG_FORMATTER_H 35*404b540aSrobert #define _GLIBCXX_DEBUG_FORMATTER_H 1 36*404b540aSrobert 37*404b540aSrobert #include <typeinfo> 38*404b540aSrobert #include <debug/debug.h> 39*404b540aSrobert 40*404b540aSrobert namespace __gnu_debug 41*404b540aSrobert { 42*404b540aSrobert using std::type_info; 43*404b540aSrobert 44*404b540aSrobert /** Determine if the two types are the same. */ 45*404b540aSrobert template<typename _Type1, typename _Type2> 46*404b540aSrobert struct __is_same 47*404b540aSrobert { 48*404b540aSrobert static const bool value = false; 49*404b540aSrobert }; 50*404b540aSrobert 51*404b540aSrobert template<typename _Type> 52*404b540aSrobert struct __is_same<_Type, _Type> 53*404b540aSrobert { 54*404b540aSrobert static const bool value = true; 55*404b540aSrobert }; 56*404b540aSrobert 57*404b540aSrobert template<bool> struct __truth { }; 58*404b540aSrobert 59*404b540aSrobert class _Safe_sequence_base; 60*404b540aSrobert 61*404b540aSrobert template<typename _Iterator, typename _Sequence> 62*404b540aSrobert class _Safe_iterator; 63*404b540aSrobert 64*404b540aSrobert template<typename _Sequence> 65*404b540aSrobert class _Safe_sequence; 66*404b540aSrobert 67*404b540aSrobert enum _Debug_msg_id 68*404b540aSrobert { 69*404b540aSrobert // General checks 70*404b540aSrobert __msg_valid_range, 71*404b540aSrobert __msg_insert_singular, 72*404b540aSrobert __msg_insert_different, 73*404b540aSrobert __msg_erase_bad, 74*404b540aSrobert __msg_erase_different, 75*404b540aSrobert __msg_subscript_oob, 76*404b540aSrobert __msg_empty, 77*404b540aSrobert __msg_unpartitioned, 78*404b540aSrobert __msg_unpartitioned_pred, 79*404b540aSrobert __msg_unsorted, 80*404b540aSrobert __msg_unsorted_pred, 81*404b540aSrobert __msg_not_heap, 82*404b540aSrobert __msg_not_heap_pred, 83*404b540aSrobert // std::bitset checks 84*404b540aSrobert __msg_bad_bitset_write, 85*404b540aSrobert __msg_bad_bitset_read, 86*404b540aSrobert __msg_bad_bitset_flip, 87*404b540aSrobert // std::list checks 88*404b540aSrobert __msg_self_splice, 89*404b540aSrobert __msg_splice_alloc, 90*404b540aSrobert __msg_splice_bad, 91*404b540aSrobert __msg_splice_other, 92*404b540aSrobert __msg_splice_overlap, 93*404b540aSrobert // iterator checks 94*404b540aSrobert __msg_init_singular, 95*404b540aSrobert __msg_init_copy_singular, 96*404b540aSrobert __msg_init_const_singular, 97*404b540aSrobert __msg_copy_singular, 98*404b540aSrobert __msg_bad_deref, 99*404b540aSrobert __msg_bad_inc, 100*404b540aSrobert __msg_bad_dec, 101*404b540aSrobert __msg_iter_subscript_oob, 102*404b540aSrobert __msg_advance_oob, 103*404b540aSrobert __msg_retreat_oob, 104*404b540aSrobert __msg_iter_compare_bad, 105*404b540aSrobert __msg_compare_different, 106*404b540aSrobert __msg_iter_order_bad, 107*404b540aSrobert __msg_order_different, 108*404b540aSrobert __msg_distance_bad, 109*404b540aSrobert __msg_distance_different, 110*404b540aSrobert // istream_iterator 111*404b540aSrobert __msg_deref_istream, 112*404b540aSrobert __msg_inc_istream, 113*404b540aSrobert // ostream_iterator 114*404b540aSrobert __msg_output_ostream, 115*404b540aSrobert // istreambuf_iterator 116*404b540aSrobert __msg_deref_istreambuf, 117*404b540aSrobert __msg_inc_istreambuf 118*404b540aSrobert }; 119*404b540aSrobert 120*404b540aSrobert class _Error_formatter 121*404b540aSrobert { 122*404b540aSrobert /// Whether an iterator is constant, mutable, or unknown 123*404b540aSrobert enum _Constness 124*404b540aSrobert { 125*404b540aSrobert __unknown_constness, 126*404b540aSrobert __const_iterator, 127*404b540aSrobert __mutable_iterator, 128*404b540aSrobert __last_constness 129*404b540aSrobert }; 130*404b540aSrobert 131*404b540aSrobert // The state of the iterator (fine-grained), if we know it. 132*404b540aSrobert enum _Iterator_state 133*404b540aSrobert { 134*404b540aSrobert __unknown_state, 135*404b540aSrobert __singular, // singular, may still be attached to a sequence 136*404b540aSrobert __begin, // dereferenceable, and at the beginning 137*404b540aSrobert __middle, // dereferenceable, not at the beginning 138*404b540aSrobert __end, // past-the-end, may be at beginning if sequence empty 139*404b540aSrobert __last_state 140*404b540aSrobert }; 141*404b540aSrobert 142*404b540aSrobert // Tags denoting the type of parameter for construction 143*404b540aSrobert struct _Is_iterator { }; 144*404b540aSrobert struct _Is_sequence { }; 145*404b540aSrobert 146*404b540aSrobert // A parameter that may be referenced by an error message 147*404b540aSrobert struct _Parameter 148*404b540aSrobert { 149*404b540aSrobert enum 150*404b540aSrobert { 151*404b540aSrobert __unused_param, 152*404b540aSrobert __iterator, 153*404b540aSrobert __sequence, 154*404b540aSrobert __integer, 155*404b540aSrobert __string 156*404b540aSrobert } _M_kind; 157*404b540aSrobert 158*404b540aSrobert union 159*404b540aSrobert { 160*404b540aSrobert // When _M_kind == __iterator 161*404b540aSrobert struct 162*404b540aSrobert { 163*404b540aSrobert const char* _M_name; 164*404b540aSrobert const void* _M_address; 165*404b540aSrobert const type_info* _M_type; 166*404b540aSrobert _Constness _M_constness; 167*404b540aSrobert _Iterator_state _M_state; 168*404b540aSrobert const void* _M_sequence; 169*404b540aSrobert const type_info* _M_seq_type; 170*404b540aSrobert } _M_iterator; 171*404b540aSrobert 172*404b540aSrobert // When _M_kind == __sequence 173*404b540aSrobert struct 174*404b540aSrobert { 175*404b540aSrobert const char* _M_name; 176*404b540aSrobert const void* _M_address; 177*404b540aSrobert const type_info* _M_type; 178*404b540aSrobert } _M_sequence; 179*404b540aSrobert 180*404b540aSrobert // When _M_kind == __integer 181*404b540aSrobert struct 182*404b540aSrobert { 183*404b540aSrobert const char* _M_name; 184*404b540aSrobert long _M_value; 185*404b540aSrobert } _M_integer; 186*404b540aSrobert 187*404b540aSrobert // When _M_kind == __string 188*404b540aSrobert struct 189*404b540aSrobert { 190*404b540aSrobert const char* _M_name; 191*404b540aSrobert const char* _M_value; 192*404b540aSrobert } _M_string; 193*404b540aSrobert } _M_variant; 194*404b540aSrobert 195*404b540aSrobert _Parameter() : _M_kind(__unused_param), _M_variant() { } 196*404b540aSrobert 197*404b540aSrobert _Parameter(long __value, const char* __name) 198*404b540aSrobert : _M_kind(__integer), _M_variant() 199*404b540aSrobert { 200*404b540aSrobert _M_variant._M_integer._M_name = __name; 201*404b540aSrobert _M_variant._M_integer._M_value = __value; 202*404b540aSrobert } 203*404b540aSrobert 204*404b540aSrobert _Parameter(const char* __value, const char* __name) 205*404b540aSrobert : _M_kind(__string), _M_variant() 206*404b540aSrobert { 207*404b540aSrobert _M_variant._M_string._M_name = __name; 208*404b540aSrobert _M_variant._M_string._M_value = __value; 209*404b540aSrobert } 210*404b540aSrobert 211*404b540aSrobert template<typename _Iterator, typename _Sequence> 212*404b540aSrobert _Parameter(const _Safe_iterator<_Iterator, _Sequence>& __it, 213*404b540aSrobert const char* __name, _Is_iterator) 214*404b540aSrobert : _M_kind(__iterator), _M_variant() 215*404b540aSrobert { 216*404b540aSrobert _M_variant._M_iterator._M_name = __name; 217*404b540aSrobert _M_variant._M_iterator._M_address = &__it; 218*404b540aSrobert _M_variant._M_iterator._M_type = &typeid(__it); 219*404b540aSrobert _M_variant._M_iterator._M_constness = 220*404b540aSrobert __is_same<_Safe_iterator<_Iterator, _Sequence>, 221*404b540aSrobert typename _Sequence::iterator>:: 222*404b540aSrobert value? __mutable_iterator : __const_iterator; 223*404b540aSrobert _M_variant._M_iterator._M_sequence = __it._M_get_sequence(); 224*404b540aSrobert _M_variant._M_iterator._M_seq_type = &typeid(_Sequence); 225*404b540aSrobert 226*404b540aSrobert if (__it._M_singular()) 227*404b540aSrobert _M_variant._M_iterator._M_state = __singular; 228*404b540aSrobert else 229*404b540aSrobert { 230*404b540aSrobert bool __is_begin = __it._M_is_begin(); 231*404b540aSrobert bool __is_end = __it._M_is_end(); 232*404b540aSrobert if (__is_end) 233*404b540aSrobert _M_variant._M_iterator._M_state = __end; 234*404b540aSrobert else if (__is_begin) 235*404b540aSrobert _M_variant._M_iterator._M_state = __begin; 236*404b540aSrobert else 237*404b540aSrobert _M_variant._M_iterator._M_state = __middle; 238*404b540aSrobert } 239*404b540aSrobert } 240*404b540aSrobert 241*404b540aSrobert template<typename _Type> 242*404b540aSrobert _Parameter(const _Type*& __it, const char* __name, _Is_iterator) 243*404b540aSrobert : _M_kind(__iterator), _M_variant() 244*404b540aSrobert { 245*404b540aSrobert _M_variant._M_iterator._M_name = __name; 246*404b540aSrobert _M_variant._M_iterator._M_address = &__it; 247*404b540aSrobert _M_variant._M_iterator._M_type = &typeid(__it); 248*404b540aSrobert _M_variant._M_iterator._M_constness = __mutable_iterator; 249*404b540aSrobert _M_variant._M_iterator._M_state = __it? __unknown_state : __singular; 250*404b540aSrobert _M_variant._M_iterator._M_sequence = 0; 251*404b540aSrobert _M_variant._M_iterator._M_seq_type = 0; 252*404b540aSrobert } 253*404b540aSrobert 254*404b540aSrobert template<typename _Type> 255*404b540aSrobert _Parameter(_Type*& __it, const char* __name, _Is_iterator) 256*404b540aSrobert : _M_kind(__iterator), _M_variant() 257*404b540aSrobert { 258*404b540aSrobert _M_variant._M_iterator._M_name = __name; 259*404b540aSrobert _M_variant._M_iterator._M_address = &__it; 260*404b540aSrobert _M_variant._M_iterator._M_type = &typeid(__it); 261*404b540aSrobert _M_variant._M_iterator._M_constness = __const_iterator; 262*404b540aSrobert _M_variant._M_iterator._M_state = __it? __unknown_state : __singular; 263*404b540aSrobert _M_variant._M_iterator._M_sequence = 0; 264*404b540aSrobert _M_variant._M_iterator._M_seq_type = 0; 265*404b540aSrobert } 266*404b540aSrobert 267*404b540aSrobert template<typename _Iterator> 268*404b540aSrobert _Parameter(const _Iterator& __it, const char* __name, _Is_iterator) 269*404b540aSrobert : _M_kind(__iterator), _M_variant() 270*404b540aSrobert { 271*404b540aSrobert _M_variant._M_iterator._M_name = __name; 272*404b540aSrobert _M_variant._M_iterator._M_address = &__it; 273*404b540aSrobert _M_variant._M_iterator._M_type = &typeid(__it); 274*404b540aSrobert _M_variant._M_iterator._M_constness = __unknown_constness; 275*404b540aSrobert _M_variant._M_iterator._M_state = 276*404b540aSrobert __gnu_debug::__check_singular(__it)? __singular : __unknown_state; 277*404b540aSrobert _M_variant._M_iterator._M_sequence = 0; 278*404b540aSrobert _M_variant._M_iterator._M_seq_type = 0; 279*404b540aSrobert } 280*404b540aSrobert 281*404b540aSrobert template<typename _Sequence> 282*404b540aSrobert _Parameter(const _Safe_sequence<_Sequence>& __seq, 283*404b540aSrobert const char* __name, _Is_sequence) 284*404b540aSrobert : _M_kind(__sequence), _M_variant() 285*404b540aSrobert { 286*404b540aSrobert _M_variant._M_sequence._M_name = __name; 287*404b540aSrobert _M_variant._M_sequence._M_address = 288*404b540aSrobert static_cast<const _Sequence*>(&__seq); 289*404b540aSrobert _M_variant._M_sequence._M_type = &typeid(_Sequence); 290*404b540aSrobert } 291*404b540aSrobert 292*404b540aSrobert template<typename _Sequence> 293*404b540aSrobert _Parameter(const _Sequence& __seq, const char* __name, _Is_sequence) 294*404b540aSrobert : _M_kind(__sequence), _M_variant() 295*404b540aSrobert { 296*404b540aSrobert _M_variant._M_sequence._M_name = __name; 297*404b540aSrobert _M_variant._M_sequence._M_address = &__seq; 298*404b540aSrobert _M_variant._M_sequence._M_type = &typeid(_Sequence); 299*404b540aSrobert } 300*404b540aSrobert 301*404b540aSrobert void 302*404b540aSrobert _M_print_field(const _Error_formatter* __formatter, 303*404b540aSrobert const char* __name) const; 304*404b540aSrobert 305*404b540aSrobert void 306*404b540aSrobert _M_print_description(const _Error_formatter* __formatter) const; 307*404b540aSrobert }; 308*404b540aSrobert 309*404b540aSrobert friend struct _Parameter; 310*404b540aSrobert 311*404b540aSrobert public: 312*404b540aSrobert template<typename _Iterator> 313*404b540aSrobert const _Error_formatter& 314*404b540aSrobert _M_iterator(const _Iterator& __it, const char* __name = 0) const 315*404b540aSrobert { 316*404b540aSrobert if (_M_num_parameters < size_t(__max_parameters)) 317*404b540aSrobert _M_parameters[_M_num_parameters++] = _Parameter(__it, __name, 318*404b540aSrobert _Is_iterator()); 319*404b540aSrobert return *this; 320*404b540aSrobert } 321*404b540aSrobert 322*404b540aSrobert const _Error_formatter& 323*404b540aSrobert _M_integer(long __value, const char* __name = 0) const 324*404b540aSrobert { 325*404b540aSrobert if (_M_num_parameters < size_t(__max_parameters)) 326*404b540aSrobert _M_parameters[_M_num_parameters++] = _Parameter(__value, __name); 327*404b540aSrobert return *this; 328*404b540aSrobert } 329*404b540aSrobert 330*404b540aSrobert const _Error_formatter& 331*404b540aSrobert _M_string(const char* __value, const char* __name = 0) const 332*404b540aSrobert { 333*404b540aSrobert if (_M_num_parameters < size_t(__max_parameters)) 334*404b540aSrobert _M_parameters[_M_num_parameters++] = _Parameter(__value, __name); 335*404b540aSrobert return *this; 336*404b540aSrobert } 337*404b540aSrobert 338*404b540aSrobert template<typename _Sequence> 339*404b540aSrobert const _Error_formatter& 340*404b540aSrobert _M_sequence(const _Sequence& __seq, const char* __name = 0) const 341*404b540aSrobert { 342*404b540aSrobert if (_M_num_parameters < size_t(__max_parameters)) 343*404b540aSrobert _M_parameters[_M_num_parameters++] = _Parameter(__seq, __name, 344*404b540aSrobert _Is_sequence()); 345*404b540aSrobert return *this; 346*404b540aSrobert } 347*404b540aSrobert 348*404b540aSrobert const _Error_formatter& 349*404b540aSrobert _M_message(const char* __text) const 350*404b540aSrobert { _M_text = __text; return *this; } 351*404b540aSrobert 352*404b540aSrobert const _Error_formatter& 353*404b540aSrobert _M_message(_Debug_msg_id __id) const; 354*404b540aSrobert 355*404b540aSrobert void 356*404b540aSrobert _M_error() const; 357*404b540aSrobert 358*404b540aSrobert private: 359*404b540aSrobert _Error_formatter(const char* __file, size_t __line) 360*404b540aSrobert : _M_file(__file), _M_line(__line), _M_num_parameters(0), _M_text(0), 361*404b540aSrobert _M_max_length(78), _M_column(1), _M_first_line(true), _M_wordwrap(false) 362*404b540aSrobert { } 363*404b540aSrobert 364*404b540aSrobert template<typename _Tp> 365*404b540aSrobert void 366*404b540aSrobert _M_format_word(char*, int, const char*, _Tp) const; 367*404b540aSrobert 368*404b540aSrobert void 369*404b540aSrobert _M_print_word(const char* __word) const; 370*404b540aSrobert 371*404b540aSrobert void 372*404b540aSrobert _M_print_string(const char* __string) const; 373*404b540aSrobert 374*404b540aSrobert enum { __max_parameters = 9 }; 375*404b540aSrobert 376*404b540aSrobert const char* _M_file; 377*404b540aSrobert size_t _M_line; 378*404b540aSrobert mutable _Parameter _M_parameters[__max_parameters]; 379*404b540aSrobert mutable size_t _M_num_parameters; 380*404b540aSrobert mutable const char* _M_text; 381*404b540aSrobert mutable size_t _M_max_length; 382*404b540aSrobert enum { _M_indent = 4 } ; 383*404b540aSrobert mutable size_t _M_column; 384*404b540aSrobert mutable bool _M_first_line; 385*404b540aSrobert mutable bool _M_wordwrap; 386*404b540aSrobert 387*404b540aSrobert public: 388*404b540aSrobert static _Error_formatter 389*404b540aSrobert _M_at(const char* __file, size_t __line) 390*404b540aSrobert { return _Error_formatter(__file, __line); } 391*404b540aSrobert }; 392*404b540aSrobert } // namespace __gnu_debug 393*404b540aSrobert 394*404b540aSrobert #endif 395