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