1/*
2 *
3 * Copyright (c) 1997
4 * Moscow Center for SPARC Technology
5 *
6 * Copyright (c) 1999
7 * Boris Fomitchev
8 *
9 * This material is provided "as is", with absolutely no warranty expressed
10 * or implied. Any use is at your own risk.
11 *
12 * Permission to use or copy this software for any purpose is hereby granted
13 * without fee, provided the above notices are retained on all copies.
14 * Permission to modify the code and to distribute modified code is granted,
15 * provided the above notices are retained, and a notice that the code was
16 * modified is included with the above copyright notice.
17 *
18 */
19
20#ifndef _STLP_DEBUG_H
21#define _STLP_DEBUG_H
22
23#if (defined (_STLP_DEBUG) || defined (_STLP_DEBUG_ALLOC)) && \
24    !defined (_STLP_ASSERTIONS)
25#  define _STLP_ASSERTIONS 1
26#endif
27
28#if defined (_STLP_ASSERTIONS)
29
30#  if !defined (_STLP_FILE__)
31#    define _STLP_FILE__ __FILE__
32#  endif
33
34_STLP_BEGIN_NAMESPACE
35
36_STLP_MOVE_TO_PRIV_NAMESPACE
37
38enum {
39  //General errors
40  _StlFormat_ERROR_RETURN,
41  _StlFormat_ASSERTION_FAILURE,
42  _StlFormat_VERBOSE_ASSERTION_FAILURE,
43  _StlMsg_INVALID_ARGUMENT,
44  //Container/Iterator related errors
45  _StlMsg_INVALID_CONTAINER,
46  _StlMsg_EMPTY_CONTAINER,
47  _StlMsg_ERASE_PAST_THE_END,
48  _StlMsg_OUT_OF_BOUNDS,
49  _StlMsg_NOT_OWNER,
50  _StlMsg_SHOULD_NOT_OWNER,
51  _StlMsg_INVALID_ITERATOR,
52  _StlMsg_INVALID_LEFTHAND_ITERATOR,
53  _StlMsg_INVALID_RIGHTHAND_ITERATOR,
54  _StlMsg_DIFFERENT_OWNERS     ,
55  _StlMsg_NOT_DEREFERENCEABLE  ,
56  _StlMsg_INVALID_RANGE        ,
57  _StlMsg_NOT_IN_RANGE_1       ,
58  _StlMsg_NOT_IN_RANGE_2       ,
59  _StlMsg_INVALID_ADVANCE      ,
60  _StlMsg_SINGULAR_ITERATOR    ,
61  //Bad predicate for sorting
62  _StlMsg_INVALID_STRICT_WEAK_PREDICATE,
63  _StlMsg_INVALID_EQUIVALENT_PREDICATE,
64  // debug alloc messages
65  _StlMsg_DBA_DELETED_TWICE    ,
66  _StlMsg_DBA_NEVER_ALLOCATED  ,
67  _StlMsg_DBA_TYPE_MISMATCH    ,
68  _StlMsg_DBA_SIZE_MISMATCH    ,
69  _StlMsg_DBA_UNDERRUN         ,
70  _StlMsg_DBA_OVERRUN          ,
71  // auto_ptr messages
72  _StlMsg_AUTO_PTR_NULL    ,
73  //Memory alignent message
74  _StlMsg_WRONG_MEMORY_ALIGNMENT,
75  _StlMsg_UNKNOWN
76  /* _StlMsg_MAX */
77};
78
79/* have to hardcode that ;() */
80#  define _StlMsg_MAX 31
81
82class __owned_link;
83class __owned_list;
84
85#  if defined (_STLP_DEBUG_MODE_THROWS)
86#    define _STLP_MESSAGE_NORETURN _STLP_FUNCTION_THROWS
87#  else
88#    define _STLP_MESSAGE_NORETURN
89#  endif
90
91template <class _Dummy>
92class __stl_debug_engine {
93public:
94  // Basic routine to report any debug message
95  // Use _STLP_DEBUG_MESSAGE to override
96  static void _STLP_MESSAGE_NORETURN _STLP_CALL _Message(const char * format_str, ...);
97
98  // Micsellanous function to report indexed error message
99  static void _STLP_CALL  _IndexedError(int __ind, const char* __f, int __l);
100
101  // Basic assertion report mechanism.
102  // Reports failed assertion via __stl_debug_message and calls _Terminate
103  // if _STLP_DEBUG_TERMINATE is specified, calls __stl_debug_terminate instead
104  static void _STLP_CALL  _Assert(const char* __expr, const char* __f, int __l);
105
106  // The same, with additional diagnostics
107  static void _STLP_CALL  _VerboseAssert(const char* __expr, int __error_ind, const char* __f, int __l);
108
109  // If exceptions are present, sends unique exception
110  // If not, calls _STLP_ABORT() to terminate
111  // Use _STLP_DEBUG_TERMINATE to override
112  static void _STLP_CALL  _Terminate();
113
114#  if defined (_STLP_DEBUG)
115  // owned_list/link delegate non-inline functions here
116
117  static bool _STLP_CALL  _Check_same_owner( const __owned_link& __i1,
118                                             const __owned_link& __i2);
119  static bool _STLP_CALL  _Check_same_or_null_owner( const __owned_link& __i1,
120                                                     const __owned_link& __i2);
121  static bool _STLP_CALL  _Check_if_owner( const __owned_list*, const __owned_link&);
122
123  static bool _STLP_CALL  _Check_if_not_owner( const __owned_list*, const __owned_link&);
124
125  static void _STLP_CALL  _Verify(const __owned_list*);
126
127  static void _STLP_CALL  _Swap_owners(__owned_list&, __owned_list&);
128
129  static void _STLP_CALL  _Invalidate_all(__owned_list*);
130
131  static void _STLP_CALL  _Set_owner(__owned_list& /*src*/, __owned_list& /*dst*/);
132
133  static void _STLP_CALL  _Stamp_all(__owned_list*, __owned_list*);
134
135  static void _STLP_CALL  _M_detach(__owned_list*, __owned_link*);
136
137  static void _STLP_CALL  _M_attach(__owned_list*, __owned_link*);
138
139  // accessor : check and get pointer to the container
140  static void* _STLP_CALL  _Get_container_ptr(const __owned_link*);
141#  endif
142
143  // debug messages and formats
144  static const char* _Message_table[_StlMsg_MAX];
145};
146
147#  undef _STLP_MESSAGE_NORETURN
148
149#  if defined (_STLP_USE_TEMPLATE_EXPORT)
150_STLP_EXPORT_TEMPLATE_CLASS __stl_debug_engine<bool>;
151#  endif
152
153typedef __stl_debug_engine<bool> __stl_debugger;
154
155_STLP_MOVE_TO_STD_NAMESPACE
156
157_STLP_END_NAMESPACE
158
159#  if !defined (_STLP_ASSERT)
160#    define _STLP_ASSERT(expr) \
161       if (!(expr)) { _STLP_PRIV __stl_debugger::_Assert( # expr, _STLP_FILE__, __LINE__); }
162#  endif
163
164#else
165#  define _STLP_ASSERT(expr)
166#endif
167
168// this section is for _STLP_DEBUG only
169#if defined (_STLP_DEBUG)
170
171#  if !defined (_STLP_VERBOSE_ASSERT)
172// fbp : new form not requiring ";"
173#    define _STLP_VERBOSE_ASSERT(expr, __diag_num) \
174       if (!(expr)) { _STLP_PRIV __stl_debugger::_VerboseAssert\
175                               ( # expr,  _STLP_PRIV __diag_num, _STLP_FILE__, __LINE__ ); \
176          }
177#  endif
178
179#  define _STLP_DEBUG_CHECK(expr) _STLP_ASSERT(expr)
180
181#  if (_STLP_DEBUG_LEVEL == _STLP_STANDARD_DBG_LEVEL)
182#    define _STLP_STD_DEBUG_CHECK(expr) _STLP_DEBUG_CHECK(expr)
183#  else
184#    define _STLP_STD_DEBUG_CHECK(expr)
185#  endif
186
187#  if !defined (_STLP_VERBOSE_RETURN)
188#    define _STLP_VERBOSE_RETURN(__expr,__diag_num) if (!(__expr)) { \
189         _STLP_PRIV __stl_debugger::_IndexedError(__diag_num, _STLP_FILE__ , __LINE__); \
190         return false; }
191#  endif
192
193#  if !defined (_STLP_VERBOSE_RETURN_0)
194#    define _STLP_VERBOSE_RETURN_0(__expr,__diag_num) if (!(__expr)) { \
195         _STLP_PRIV __stl_debugger::_IndexedError(__diag_num, _STLP_FILE__, __LINE__); \
196         return 0; }
197#  endif
198
199#  ifndef _STLP_INTERNAL_THREADS_H
200#    include <stl/_threads.h>
201#  endif
202
203#  ifndef _STLP_INTERNAL_ITERATOR_BASE_H
204#    include <stl/_iterator_base.h>
205#  endif
206
207#  ifndef _STLP_TYPE_TRAITS_H
208#    include <stl/type_traits.h>
209#  endif
210
211_STLP_BEGIN_NAMESPACE
212
213_STLP_MOVE_TO_PRIV_NAMESPACE
214
215/*
216 * Special debug iterator traits having an additionnal static member
217 * method _Check. It is used by the slist debug implementation to check
218 * the special before_begin iterator.
219 */
220template <class _Traits>
221struct _DbgTraits : _Traits {
222  typedef _DbgTraits<typename _Traits::_ConstTraits> _ConstTraits;
223  typedef _DbgTraits<typename _Traits::_NonConstTraits> _NonConstTraits;
224
225  template <class _Iterator>
226  static bool _Check(const _Iterator&) {return true;}
227};
228
229//=============================================================
230template <class _Iterator>
231inline bool  _STLP_CALL __valid_range(const _Iterator& __i1 ,const _Iterator& __i2,
232                                      const random_access_iterator_tag&)
233{ return (__i1 < __i2) || (__i1 == __i2); }
234
235template <class _Iterator>
236inline bool  _STLP_CALL __valid_range(const _Iterator& __i1 ,const _Iterator& __i2,
237                                      const bidirectional_iterator_tag&) {
238  // check if comparable
239  bool __dummy(__i1==__i2);
240  return (__dummy==__dummy);
241}
242
243template <class _Iterator>
244inline bool  _STLP_CALL __valid_range(const _Iterator& __i1 ,const _Iterator& __i2,
245                                      const forward_iterator_tag&) {
246  // check if comparable
247  bool __dummy(__i1==__i2);
248  return (__dummy==__dummy);
249}
250
251template <class _Iterator>
252inline bool  _STLP_CALL __valid_range(const _Iterator&,const _Iterator&,
253                                      const input_iterator_tag&)
254{ return true; }
255
256template <class _Iterator>
257inline bool  _STLP_CALL __valid_range(const _Iterator&,const _Iterator&,
258                                      const output_iterator_tag&)
259{ return true; }
260
261template <class _Iterator>
262inline bool _STLP_CALL __valid_range(const _Iterator& __i1, const _Iterator& __i2)
263{ return __valid_range(__i1,__i2,_STLP_ITERATOR_CATEGORY(__i1, _Iterator)); }
264
265// Note : that means in range [i1, i2].
266template <class _Iterator>
267inline bool  _STLP_CALL stlp_in_range(const _Iterator& _It,
268                                      const _Iterator& __i1, const _Iterator& __i2)
269{ return __valid_range(__i1,_It) && __valid_range(_It,__i2); }
270
271template <class _Iterator>
272inline bool  _STLP_CALL stlp_in_range(const _Iterator& __first, const _Iterator& __last,
273                                      const _Iterator& __start, const _Iterator& __finish)
274{ return __valid_range(__first,__last) && __valid_range(__start,__first) && __valid_range(__last,__finish); }
275
276//==========================================================
277class _STLP_CLASS_DECLSPEC __owned_link {
278public:
279  // Note: This and the following special defines for compiling under Windows CE under ARM
280  // is needed for correctly using _STLP_DEBUG mode. This comes from a bug in the ARM
281  // compiler where checked iterators that are passed by value call _M_attach with the wrong
282  // this pointer and calling _M_detach can't find the correct pointer to the __owned_link.
283  // This is circumvented by managing a _M_self pointer that points to the correct value.
284  // Ugly but works.
285#if defined(_STLP_WCE) && defined(_ARM_)
286  __owned_link() : _M_self(this), _M_owner(0) {}
287  __owned_link(const __owned_list* __c) : _M_self(this), _M_owner(0), _M_next(0)
288  { __stl_debugger::_M_attach(__CONST_CAST(__owned_list*,__c), this); }
289  __owned_link(const __owned_link& __rhs): _M_self(this), _M_owner(0)
290  { __stl_debugger::_M_attach(__CONST_CAST(__owned_list*,__rhs._M_owner), this); }
291#else
292  __owned_link() : _M_owner(0) {}
293  __owned_link(const __owned_list* __c) : _M_owner(0), _M_next(0)
294  { __stl_debugger::_M_attach(__CONST_CAST(__owned_list*,__c), this); }
295  __owned_link(const __owned_link& __rhs): _M_owner(0)
296  { __stl_debugger::_M_attach(__CONST_CAST(__owned_list*,__rhs._M_owner), this); }
297#endif
298  __owned_link& operator=(const __owned_link& __rhs) {
299    __owned_list* __new_owner = __CONST_CAST(__owned_list*,__rhs._M_owner);
300    __owned_list* __old_owner = _M_owner;
301    if ( __old_owner != __new_owner ) {
302      __stl_debugger::_M_detach(__old_owner, this);
303      __stl_debugger::_M_attach(__new_owner, this);
304    }
305    return *this;
306  }
307#if defined(_STLP_WCE) && defined(_ARM_)
308  ~__owned_link() {
309    __stl_debugger::_M_detach(_M_owner, _M_self);
310    _Invalidate();
311  }
312#else
313  ~__owned_link() {
314    __stl_debugger::_M_detach(_M_owner, this);
315    _Invalidate();
316  }
317#endif
318
319  const __owned_list* _Owner() const { return _M_owner; }
320  __owned_list* _Owner() { return _M_owner; }
321  void _Set_owner(const __owned_list* __o) { _M_owner= __CONST_CAST(__owned_list*,__o); }
322  bool _Valid() const { return _M_owner != 0; }
323  void _Invalidate() { _M_owner = 0; _M_next = 0; }
324  void _Link_to_self() { _M_next = 0; }
325
326  __owned_link* _Next() { return _M_next; }
327  const __owned_link* _Next() const { return _M_next; }
328
329public:
330#if defined(_STLP_WCE) && defined(_ARM_)
331  __owned_link* _M_self;
332#endif
333
334  __owned_list* _M_owner;
335  __owned_link* _M_next;
336};
337
338
339class _STLP_CLASS_DECLSPEC __owned_list {
340public:
341  __owned_list(void* __o) {
342    //    fprintf(stderr, "__owned_list(): %p\n",(void*)this);
343    _M_node._M_owner = __REINTERPRET_CAST(__owned_list*,__o);
344    _M_node._M_next = 0;
345  }
346  ~__owned_list() {
347    //    fprintf(stderr, "~__owned_list(): %p\n",(void*)this);
348    _Invalidate_all();
349    // that prevents detach
350    _M_node._Invalidate();
351  }
352  const void* _Owner() const { return (const void*)_M_node._M_owner; }
353  void* _Owner() { return (void*)_M_node._M_owner; }
354  bool  _Valid() const { return _M_node._M_owner != 0; }
355  void _Invalidate() { _M_node._M_owner = 0; }
356
357  __owned_link* _First() { return _M_node._Next(); }
358  __owned_link* _Last() { return 0 ; }
359
360  const __owned_link* _First() const { return (__owned_link*)_M_node._M_next; }
361  const __owned_link* _Last() const { return 0 ;}
362
363  void _Verify() const { __stl_debugger::_Verify(this); }
364  void _Swap_owners(__owned_list& __y) { __stl_debugger::_Swap_owners(*this, __y); }
365  void _Invalidate_all() { __stl_debugger::_Invalidate_all(this); }
366  void _Set_owner(__owned_list& __y) { __stl_debugger::_Set_owner(*this, __y); }
367
368  mutable __owned_link _M_node;
369  mutable _STLP_mutex  _M_lock;
370
371private:
372  // should never be called, should be left not implemented,
373  // but some compilers complain about it ;(
374  __owned_list(const __owned_list&){}
375  __owned_list& operator = (const __owned_list&) { return *this; }
376
377  friend class __owned_link;
378  friend class __stl_debug_engine<bool>;
379};
380
381
382//==========================================================
383
384// forward declaratioins
385
386template <class _Iterator>
387bool _STLP_CALL __check_range(const _Iterator&, const _Iterator&);
388template <class _Iterator>
389bool _STLP_CALL __check_range(const _Iterator&,
390                              const _Iterator&, const _Iterator&);
391template <class _Iterator>
392bool _STLP_CALL __check_range(const _Iterator&, const _Iterator& ,
393                              const _Iterator&, const _Iterator& );
394template <class _Tp>
395bool _STLP_CALL __check_ptr_range(const _Tp*, const _Tp*);
396
397template <class _Iterator>
398void _STLP_CALL __invalidate_range(const __owned_list* __base,
399                                   const _Iterator& __first,
400                                   const _Iterator& __last);
401
402template <class _Iterator>
403void _STLP_CALL __invalidate_iterator(const __owned_list* __base,
404                                      const _Iterator& __it);
405
406template <class _Iterator>
407void _STLP_CALL __change_range_owner(const _Iterator& __first,
408                                     const _Iterator& __last,
409                                     const __owned_list* __dst);
410
411template <class _Iterator>
412void  _STLP_CALL __change_ite_owner(const _Iterator& __it,
413                                    const __owned_list* __dst);
414
415//============================================================
416inline bool _STLP_CALL
417__check_same_owner(const __owned_link& __i1, const __owned_link& __i2)
418{ return __stl_debugger::_Check_same_owner(__i1,__i2); }
419
420inline bool _STLP_CALL
421__check_same_or_null_owner(const __owned_link& __i1, const __owned_link& __i2)
422{ return __stl_debugger::_Check_same_or_null_owner(__i1,__i2); }
423
424template <class _Iterator>
425inline bool _STLP_CALL  __check_if_owner( const __owned_list* __owner,
426                                          const _Iterator& __it)
427{ return __stl_debugger::_Check_if_owner(__owner, (const __owned_link&)__it); }
428
429template <class _Iterator>
430inline bool _STLP_CALL __check_if_not_owner( const __owned_list* __owner,
431                                             const _Iterator& __it)
432{ return __stl_debugger::_Check_if_not_owner(__owner, (const __owned_link&)__it); }
433
434_STLP_MOVE_TO_STD_NAMESPACE
435
436_STLP_END_NAMESPACE
437
438#else
439#  define _STLP_VERBOSE_ASSERT(expr, diagnostic)
440#  define _STLP_DEBUG_CHECK(expr)
441#endif /* _STLP_DEBUG */
442
443#if defined (_STLP_ASSERTIONS)
444
445#  if !defined (_STLP_ASSERT_MSG_TRAILER)
446#    define _STLP_ASSERT_MSG_TRAILER
447#  endif
448
449// dwa 12/30/98 - if _STLP_DEBUG_MESSAGE is defined, the user can supply own definition.
450#  if !defined (_STLP_DEBUG_MESSAGE)
451#    define __stl_debug_message __stl_debugger::_Message
452#  else
453extern  void __stl_debug_message(const char * format_str, ...);
454#  endif
455
456// fbp: if _STLP_DEBUG_TERMINATE is defined, the user can supply own definition.
457#  if !defined (_STLP_DEBUG_TERMINATE)
458#    define __stl_debug_terminate __stl_debugger::_Terminate
459#  else
460extern  void __stl_debug_terminate();
461#  endif
462
463#endif
464
465#if defined (_STLP_ASSERTIONS) && !defined (_STLP_LINK_TIME_INSTANTIATION)
466#  include <stl/debug/_debug.c>
467#endif
468
469#endif /* DEBUG_H */
470
471// Local Variables:
472// mode:C++
473// End:
474