1132720Skan// Debug-mode error formatting implementation -*- C++ -*- 2132720Skan 3169691Skan// Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. 4132720Skan// 5132720Skan// This file is part of the GNU ISO C++ Library. This library is free 6132720Skan// software; you can redistribute it and/or modify it under the 7132720Skan// terms of the GNU General Public License as published by the 8132720Skan// Free Software Foundation; either version 2, or (at your option) 9132720Skan// any later version. 10132720Skan 11132720Skan// This library is distributed in the hope that it will be useful, 12132720Skan// but WITHOUT ANY WARRANTY; without even the implied warranty of 13132720Skan// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14132720Skan// GNU General Public License for more details. 15132720Skan 16132720Skan// You should have received a copy of the GNU General Public License along 17132720Skan// with this library; see the file COPYING. If not, write to the Free 18169691Skan// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 19132720Skan// USA. 20132720Skan 21132720Skan// As a special exception, you may use this file as part of a free software 22132720Skan// library without restriction. Specifically, if other files instantiate 23132720Skan// templates or use macros or inline functions from this file, or you compile 24132720Skan// this file and link it with other files to produce an executable, this 25132720Skan// file does not by itself cause the resulting executable to be covered by 26132720Skan// the GNU General Public License. This exception does not however 27132720Skan// invalidate any other reasons why the executable file might be covered by 28132720Skan// the GNU General Public License. 29132720Skan 30169691Skan/** @file debug/formatter.h 31169691Skan * This file is a GNU debug extension to the Standard C++ Library. 32169691Skan */ 33169691Skan 34132720Skan#ifndef _GLIBCXX_DEBUG_FORMATTER_H 35132720Skan#define _GLIBCXX_DEBUG_FORMATTER_H 1 36132720Skan 37132720Skan#include <typeinfo> 38132720Skan#include <debug/debug.h> 39132720Skan 40132720Skannamespace __gnu_debug 41132720Skan{ 42132720Skan using std::type_info; 43132720Skan 44132720Skan /** Determine if the two types are the same. */ 45132720Skan template<typename _Type1, typename _Type2> 46132720Skan struct __is_same 47132720Skan { 48132720Skan static const bool value = false; 49132720Skan }; 50132720Skan 51132720Skan template<typename _Type> 52132720Skan struct __is_same<_Type, _Type> 53132720Skan { 54132720Skan static const bool value = true; 55132720Skan }; 56132720Skan 57132720Skan template<bool> struct __truth { }; 58132720Skan 59132720Skan class _Safe_sequence_base; 60132720Skan 61132720Skan template<typename _Iterator, typename _Sequence> 62132720Skan class _Safe_iterator; 63132720Skan 64132720Skan template<typename _Sequence> 65132720Skan class _Safe_sequence; 66132720Skan 67132720Skan enum _Debug_msg_id 68132720Skan { 69132720Skan // General checks 70132720Skan __msg_valid_range, 71132720Skan __msg_insert_singular, 72132720Skan __msg_insert_different, 73132720Skan __msg_erase_bad, 74132720Skan __msg_erase_different, 75132720Skan __msg_subscript_oob, 76132720Skan __msg_empty, 77132720Skan __msg_unpartitioned, 78132720Skan __msg_unpartitioned_pred, 79132720Skan __msg_unsorted, 80132720Skan __msg_unsorted_pred, 81132720Skan __msg_not_heap, 82132720Skan __msg_not_heap_pred, 83132720Skan // std::bitset checks 84132720Skan __msg_bad_bitset_write, 85132720Skan __msg_bad_bitset_read, 86132720Skan __msg_bad_bitset_flip, 87132720Skan // std::list checks 88132720Skan __msg_self_splice, 89132720Skan __msg_splice_alloc, 90132720Skan __msg_splice_bad, 91132720Skan __msg_splice_other, 92132720Skan __msg_splice_overlap, 93132720Skan // iterator checks 94132720Skan __msg_init_singular, 95132720Skan __msg_init_copy_singular, 96132720Skan __msg_init_const_singular, 97132720Skan __msg_copy_singular, 98132720Skan __msg_bad_deref, 99132720Skan __msg_bad_inc, 100132720Skan __msg_bad_dec, 101132720Skan __msg_iter_subscript_oob, 102132720Skan __msg_advance_oob, 103132720Skan __msg_retreat_oob, 104132720Skan __msg_iter_compare_bad, 105132720Skan __msg_compare_different, 106132720Skan __msg_iter_order_bad, 107132720Skan __msg_order_different, 108132720Skan __msg_distance_bad, 109132720Skan __msg_distance_different, 110132720Skan // istream_iterator 111132720Skan __msg_deref_istream, 112132720Skan __msg_inc_istream, 113132720Skan // ostream_iterator 114132720Skan __msg_output_ostream, 115132720Skan // istreambuf_iterator 116132720Skan __msg_deref_istreambuf, 117132720Skan __msg_inc_istreambuf 118132720Skan }; 119132720Skan 120132720Skan class _Error_formatter 121132720Skan { 122132720Skan /// Whether an iterator is constant, mutable, or unknown 123132720Skan enum _Constness 124132720Skan { 125132720Skan __unknown_constness, 126132720Skan __const_iterator, 127132720Skan __mutable_iterator, 128132720Skan __last_constness 129132720Skan }; 130132720Skan 131132720Skan // The state of the iterator (fine-grained), if we know it. 132132720Skan enum _Iterator_state 133132720Skan { 134132720Skan __unknown_state, 135132720Skan __singular, // singular, may still be attached to a sequence 136132720Skan __begin, // dereferenceable, and at the beginning 137132720Skan __middle, // dereferenceable, not at the beginning 138132720Skan __end, // past-the-end, may be at beginning if sequence empty 139132720Skan __last_state 140132720Skan }; 141132720Skan 142132720Skan // Tags denoting the type of parameter for construction 143132720Skan struct _Is_iterator { }; 144132720Skan struct _Is_sequence { }; 145132720Skan 146132720Skan // A parameter that may be referenced by an error message 147132720Skan struct _Parameter 148132720Skan { 149132720Skan enum 150132720Skan { 151132720Skan __unused_param, 152132720Skan __iterator, 153132720Skan __sequence, 154132720Skan __integer, 155132720Skan __string 156132720Skan } _M_kind; 157132720Skan 158132720Skan union 159132720Skan { 160132720Skan // When _M_kind == __iterator 161132720Skan struct 162132720Skan { 163132720Skan const char* _M_name; 164132720Skan const void* _M_address; 165132720Skan const type_info* _M_type; 166132720Skan _Constness _M_constness; 167132720Skan _Iterator_state _M_state; 168132720Skan const void* _M_sequence; 169132720Skan const type_info* _M_seq_type; 170132720Skan } _M_iterator; 171132720Skan 172132720Skan // When _M_kind == __sequence 173132720Skan struct 174132720Skan { 175132720Skan const char* _M_name; 176132720Skan const void* _M_address; 177132720Skan const type_info* _M_type; 178132720Skan } _M_sequence; 179132720Skan 180132720Skan // When _M_kind == __integer 181132720Skan struct 182132720Skan { 183132720Skan const char* _M_name; 184132720Skan long _M_value; 185132720Skan } _M_integer; 186132720Skan 187132720Skan // When _M_kind == __string 188132720Skan struct 189132720Skan { 190132720Skan const char* _M_name; 191132720Skan const char* _M_value; 192132720Skan } _M_string; 193132720Skan } _M_variant; 194132720Skan 195132720Skan _Parameter() : _M_kind(__unused_param), _M_variant() { } 196132720Skan 197132720Skan _Parameter(long __value, const char* __name) 198132720Skan : _M_kind(__integer), _M_variant() 199132720Skan { 200132720Skan _M_variant._M_integer._M_name = __name; 201132720Skan _M_variant._M_integer._M_value = __value; 202132720Skan } 203132720Skan 204132720Skan _Parameter(const char* __value, const char* __name) 205132720Skan : _M_kind(__string), _M_variant() 206132720Skan { 207132720Skan _M_variant._M_string._M_name = __name; 208132720Skan _M_variant._M_string._M_value = __value; 209132720Skan } 210132720Skan 211132720Skan template<typename _Iterator, typename _Sequence> 212132720Skan _Parameter(const _Safe_iterator<_Iterator, _Sequence>& __it, 213132720Skan const char* __name, _Is_iterator) 214132720Skan : _M_kind(__iterator), _M_variant() 215132720Skan { 216132720Skan _M_variant._M_iterator._M_name = __name; 217132720Skan _M_variant._M_iterator._M_address = &__it; 218132720Skan _M_variant._M_iterator._M_type = &typeid(__it); 219132720Skan _M_variant._M_iterator._M_constness = 220132720Skan __is_same<_Safe_iterator<_Iterator, _Sequence>, 221132720Skan typename _Sequence::iterator>:: 222132720Skan value? __mutable_iterator : __const_iterator; 223132720Skan _M_variant._M_iterator._M_sequence = __it._M_get_sequence(); 224132720Skan _M_variant._M_iterator._M_seq_type = &typeid(_Sequence); 225132720Skan 226132720Skan if (__it._M_singular()) 227132720Skan _M_variant._M_iterator._M_state = __singular; 228132720Skan else 229132720Skan { 230132720Skan bool __is_begin = __it._M_is_begin(); 231132720Skan bool __is_end = __it._M_is_end(); 232132720Skan if (__is_end) 233132720Skan _M_variant._M_iterator._M_state = __end; 234132720Skan else if (__is_begin) 235132720Skan _M_variant._M_iterator._M_state = __begin; 236132720Skan else 237132720Skan _M_variant._M_iterator._M_state = __middle; 238132720Skan } 239132720Skan } 240132720Skan 241132720Skan template<typename _Type> 242132720Skan _Parameter(const _Type*& __it, const char* __name, _Is_iterator) 243132720Skan : _M_kind(__iterator), _M_variant() 244132720Skan { 245132720Skan _M_variant._M_iterator._M_name = __name; 246132720Skan _M_variant._M_iterator._M_address = &__it; 247132720Skan _M_variant._M_iterator._M_type = &typeid(__it); 248132720Skan _M_variant._M_iterator._M_constness = __mutable_iterator; 249132720Skan _M_variant._M_iterator._M_state = __it? __unknown_state : __singular; 250132720Skan _M_variant._M_iterator._M_sequence = 0; 251132720Skan _M_variant._M_iterator._M_seq_type = 0; 252132720Skan } 253132720Skan 254132720Skan template<typename _Type> 255132720Skan _Parameter(_Type*& __it, const char* __name, _Is_iterator) 256132720Skan : _M_kind(__iterator), _M_variant() 257132720Skan { 258132720Skan _M_variant._M_iterator._M_name = __name; 259132720Skan _M_variant._M_iterator._M_address = &__it; 260132720Skan _M_variant._M_iterator._M_type = &typeid(__it); 261132720Skan _M_variant._M_iterator._M_constness = __const_iterator; 262132720Skan _M_variant._M_iterator._M_state = __it? __unknown_state : __singular; 263132720Skan _M_variant._M_iterator._M_sequence = 0; 264132720Skan _M_variant._M_iterator._M_seq_type = 0; 265132720Skan } 266132720Skan 267132720Skan template<typename _Iterator> 268132720Skan _Parameter(const _Iterator& __it, const char* __name, _Is_iterator) 269132720Skan : _M_kind(__iterator), _M_variant() 270132720Skan { 271132720Skan _M_variant._M_iterator._M_name = __name; 272132720Skan _M_variant._M_iterator._M_address = &__it; 273132720Skan _M_variant._M_iterator._M_type = &typeid(__it); 274132720Skan _M_variant._M_iterator._M_constness = __unknown_constness; 275132720Skan _M_variant._M_iterator._M_state = 276132720Skan __gnu_debug::__check_singular(__it)? __singular : __unknown_state; 277132720Skan _M_variant._M_iterator._M_sequence = 0; 278132720Skan _M_variant._M_iterator._M_seq_type = 0; 279132720Skan } 280132720Skan 281132720Skan template<typename _Sequence> 282132720Skan _Parameter(const _Safe_sequence<_Sequence>& __seq, 283132720Skan const char* __name, _Is_sequence) 284132720Skan : _M_kind(__sequence), _M_variant() 285132720Skan { 286132720Skan _M_variant._M_sequence._M_name = __name; 287132720Skan _M_variant._M_sequence._M_address = 288132720Skan static_cast<const _Sequence*>(&__seq); 289132720Skan _M_variant._M_sequence._M_type = &typeid(_Sequence); 290132720Skan } 291132720Skan 292132720Skan template<typename _Sequence> 293132720Skan _Parameter(const _Sequence& __seq, const char* __name, _Is_sequence) 294132720Skan : _M_kind(__sequence), _M_variant() 295132720Skan { 296132720Skan _M_variant._M_sequence._M_name = __name; 297132720Skan _M_variant._M_sequence._M_address = &__seq; 298132720Skan _M_variant._M_sequence._M_type = &typeid(_Sequence); 299132720Skan } 300132720Skan 301132720Skan void 302132720Skan _M_print_field(const _Error_formatter* __formatter, 303132720Skan const char* __name) const; 304132720Skan 305132720Skan void 306132720Skan _M_print_description(const _Error_formatter* __formatter) const; 307132720Skan }; 308132720Skan 309132720Skan friend struct _Parameter; 310132720Skan 311132720Skan public: 312132720Skan template<typename _Iterator> 313132720Skan const _Error_formatter& 314132720Skan _M_iterator(const _Iterator& __it, const char* __name = 0) const 315132720Skan { 316169691Skan if (_M_num_parameters < size_t(__max_parameters)) 317132720Skan _M_parameters[_M_num_parameters++] = _Parameter(__it, __name, 318132720Skan _Is_iterator()); 319132720Skan return *this; 320132720Skan } 321132720Skan 322132720Skan const _Error_formatter& 323132720Skan _M_integer(long __value, const char* __name = 0) const 324132720Skan { 325169691Skan if (_M_num_parameters < size_t(__max_parameters)) 326132720Skan _M_parameters[_M_num_parameters++] = _Parameter(__value, __name); 327132720Skan return *this; 328132720Skan } 329132720Skan 330132720Skan const _Error_formatter& 331132720Skan _M_string(const char* __value, const char* __name = 0) const 332132720Skan { 333169691Skan if (_M_num_parameters < size_t(__max_parameters)) 334132720Skan _M_parameters[_M_num_parameters++] = _Parameter(__value, __name); 335132720Skan return *this; 336132720Skan } 337132720Skan 338132720Skan template<typename _Sequence> 339132720Skan const _Error_formatter& 340132720Skan _M_sequence(const _Sequence& __seq, const char* __name = 0) const 341132720Skan { 342169691Skan if (_M_num_parameters < size_t(__max_parameters)) 343132720Skan _M_parameters[_M_num_parameters++] = _Parameter(__seq, __name, 344132720Skan _Is_sequence()); 345132720Skan return *this; 346132720Skan } 347132720Skan 348132720Skan const _Error_formatter& 349132720Skan _M_message(const char* __text) const 350132720Skan { _M_text = __text; return *this; } 351132720Skan 352132720Skan const _Error_formatter& 353132720Skan _M_message(_Debug_msg_id __id) const; 354132720Skan 355132720Skan void 356132720Skan _M_error() const; 357132720Skan 358132720Skan private: 359132720Skan _Error_formatter(const char* __file, size_t __line) 360132720Skan : _M_file(__file), _M_line(__line), _M_num_parameters(0), _M_text(0), 361132720Skan _M_max_length(78), _M_column(1), _M_first_line(true), _M_wordwrap(false) 362132720Skan { } 363132720Skan 364132720Skan template<typename _Tp> 365132720Skan void 366132720Skan _M_format_word(char*, int, const char*, _Tp) const; 367132720Skan 368132720Skan void 369132720Skan _M_print_word(const char* __word) const; 370132720Skan 371132720Skan void 372132720Skan _M_print_string(const char* __string) const; 373132720Skan 374132720Skan enum { __max_parameters = 9 }; 375132720Skan 376132720Skan const char* _M_file; 377132720Skan size_t _M_line; 378132720Skan mutable _Parameter _M_parameters[__max_parameters]; 379132720Skan mutable size_t _M_num_parameters; 380132720Skan mutable const char* _M_text; 381132720Skan mutable size_t _M_max_length; 382132720Skan enum { _M_indent = 4 } ; 383132720Skan mutable size_t _M_column; 384132720Skan mutable bool _M_first_line; 385132720Skan mutable bool _M_wordwrap; 386132720Skan 387132720Skan public: 388132720Skan static _Error_formatter 389132720Skan _M_at(const char* __file, size_t __line) 390132720Skan { return _Error_formatter(__file, __line); } 391132720Skan }; 392132720Skan} // namespace __gnu_debug 393132720Skan 394132720Skan#endif 395