source: ntrip/trunk/BNC/newmat/myexcept.cpp@ 5237

Last change on this file since 5237 was 2013, checked in by mervart, 15 years ago

* empty log message *

File size: 13.2 KB
Line 
1/// \ingroup rbd_common
2///@{
3
4/// \file myexcept.cpp
5/// Exception handler.
6/// The low level classes for
7/// - my exception class hierarchy
8/// - the functions needed for my simulated exceptions
9/// - the Tracer mechanism
10/// - routines for checking whether new and delete calls are balanced
11///
12
13// Copyright (C) 1993,4,6: R B Davies
14
15
16#define WANT_STREAM // include.h will get stream fns
17#define WANT_STRING
18
19#include "include.h" // include standard files
20
21
22#include "myexcept.h" // for exception handling
23
24#ifdef use_namespace
25namespace RBD_COMMON {
26#endif
27
28#ifdef USE_STD_NAMESPACE
29using namespace std;
30#endif
31
32//#define REG_DEREG // for print out uses of new/delete
33//#define CLEAN_LIST // to print entries being added to
34 // or deleted from cleanup list
35
36#ifdef SimulateExceptions
37
38void Throw()
39{
40 for (Janitor* jan = JumpBase::jl->janitor; jan; jan = jan->NextJanitor)
41 jan->CleanUp();
42 JumpItem* jx = JumpBase::jl->ji; // previous jumpbase;
43 if ( !jx ) { Terminate(); } // jl was initial JumpItem
44 JumpBase::jl = jx; // drop down a level; cannot be in front
45 // of previous line
46 Tracer::last = JumpBase::jl->trace;
47 longjmp(JumpBase::jl->env, 1);
48}
49
50#endif // end of simulate exceptions
51
52
53unsigned long BaseException::Select;
54char* BaseException::what_error;
55int BaseException::SoFar;
56int BaseException::LastOne;
57
58BaseException::BaseException(const char* a_what)
59{
60 Select++; SoFar = 0;
61 if (!what_error) // make space for exception message
62 {
63 LastOne = 511;
64 what_error = new char[512];
65 if (!what_error) // fail to make space
66 {
67 LastOne = 0;
68 what_error = (char *)"No heap space for exception message\n";
69 }
70 }
71 AddMessage("\n\nAn exception has been thrown\n");
72 AddMessage(a_what);
73 if (a_what) Tracer::AddTrace();
74}
75
76void BaseException::AddMessage(const char* a_what)
77{
78 if (a_what)
79 {
80 int l = strlen(a_what); int r = LastOne - SoFar;
81 if (l < r) { strcpy(what_error+SoFar, a_what); SoFar += l; }
82 else if (r > 0)
83 {
84 strncpy(what_error+SoFar, a_what, r);
85 what_error[LastOne] = 0;
86 SoFar = LastOne;
87 }
88 }
89}
90
91void BaseException::AddInt(int value)
92{
93 bool negative;
94 if (value == 0) { AddMessage("0"); return; }
95 else if (value < 0) { value = -value; negative = true; }
96 else negative = false;
97 int n = 0; int v = value; // how many digits will we need?
98 while (v > 0) { v /= 10; n++; }
99 if (negative) n++;
100 if (LastOne-SoFar < n) { AddMessage("***"); return; }
101
102 SoFar += n; n = SoFar; what_error[n] = 0;
103 while (value > 0)
104 {
105 int nv = value / 10; int rm = value - nv * 10; value = nv;
106 what_error[--n] = (char)(rm + '0');
107 }
108 if (negative) what_error[--n] = '-';
109 return;
110}
111
112void Tracer::PrintTrace()
113{
114 cout << "\n";
115 for (Tracer* et = last; et; et=et->previous)
116 cout << " * " << et->entry << "\n";
117}
118
119void Tracer::AddTrace()
120{
121 if (last)
122 {
123 BaseException::AddMessage("Trace: ");
124 BaseException::AddMessage(last->entry);
125 for (Tracer* et = last->previous; et; et=et->previous)
126 {
127 BaseException::AddMessage("; ");
128 BaseException::AddMessage(et->entry);
129 }
130 BaseException::AddMessage(".\n");
131 }
132}
133
134#ifdef SimulateExceptions
135
136
137Janitor::Janitor()
138{
139 if (do_not_link)
140 {
141 do_not_link = false; NextJanitor = 0; OnStack = false;
142#ifdef CLEAN_LIST
143 cout << "Not added to clean-list " << (unsigned long)this << "\n";
144#endif
145 }
146 else
147 {
148 OnStack = true;
149#ifdef CLEAN_LIST
150 cout << "Add to clean-list " << (unsigned long)this << "\n";
151#endif
152 NextJanitor = JumpBase::jl->janitor; JumpBase::jl->janitor=this;
153 }
154}
155
156Janitor::~Janitor()
157{
158 // expect the item to be deleted to be first on list
159 // but must be prepared to search list
160 if (OnStack)
161 {
162#ifdef CLEAN_LIST
163 cout << "Delete from clean-list " << (unsigned long)this << "\n";
164#endif
165 Janitor* lastjan = JumpBase::jl->janitor;
166 if (this == lastjan) JumpBase::jl->janitor = NextJanitor;
167 else
168 {
169 for (Janitor* jan = lastjan->NextJanitor; jan;
170 jan = lastjan->NextJanitor)
171 {
172 if (jan==this)
173 { lastjan->NextJanitor = jan->NextJanitor; return; }
174 lastjan=jan;
175 }
176
177 Throw(BaseException(
178"Cannot resolve memory linked list\nSee notes in myexcept.cpp for details\n"
179 ));
180
181
182// This message occurs when a call to ~Janitor() occurs, apparently
183// without a corresponding call to Janitor(). This could happen if my
184// way of deciding whether a constructor is being called by new
185// fails.
186
187// It may happen if you are using my simulated exceptions and also have
188// your compiler s exceptions turned on.
189
190// It can also happen if you have a class derived from Janitor
191// which does not include a copy constructor [ eg X(const &X) ].
192// Possibly also if delete is applied an object on the stack (ie not
193// called by new). Otherwise, it is a bug in myexcept or your compiler.
194// If you do not #define TEMPS_DESTROYED_QUICKLY you will get this
195// error with Microsoft C 7.0. There are probably situations where
196// you will get this when you do define TEMPS_DESTROYED_QUICKLY. This
197// is a bug in MSC. Beware of "operator" statements for defining
198// conversions; particularly for converting from a Base class to a
199// Derived class.
200
201// You may get away with simply deleting this error message and Throw
202// statement if you can not find a better way of overcoming the
203// problem. In any case please tell me if you get this error message,
204// particularly for compilers apart from Microsoft C 7.0.
205
206
207 }
208 }
209}
210
211JumpItem* JumpBase::jl; // will be set to zero
212jmp_buf JumpBase::env;
213bool Janitor::do_not_link; // will be set to false
214
215
216int JanitorInitializer::ref_count;
217
218JanitorInitializer::JanitorInitializer()
219{
220 if (ref_count++ == 0) new JumpItem;
221 // need JumpItem at head of list
222}
223
224#endif // end of SimulateExceptions
225
226Tracer* Tracer::last; // will be set to zero
227
228
229void Terminate()
230{
231 cout << "\n\nThere has been an exception with no handler - exiting";
232 const char* what = BaseException::what();
233 if (what) cout << what << "\n";
234 exit(1);
235}
236
237
238
239#ifdef DO_FREE_CHECK
240// Routines for tracing whether new and delete calls are balanced
241
242FreeCheckLink::FreeCheckLink() : next(FreeCheck::next)
243 { FreeCheck::next = this; }
244
245FCLClass::FCLClass(void* t, char* name) : ClassName(name) { ClassStore=t; }
246
247FCLRealArray::FCLRealArray(void* t, char* o, int s)
248 : Operation(o), size(s) { ClassStore=t; }
249
250FCLIntArray::FCLIntArray(void* t, char* o, int s)
251 : Operation(o), size(s) { ClassStore=t; }
252
253FreeCheckLink* FreeCheck::next;
254int FreeCheck::BadDelete;
255
256void FCLClass::Report()
257{ cout << " " << ClassName << " " << (unsigned long)ClassStore << "\n"; }
258
259void FCLRealArray::Report()
260{
261 cout << " " << Operation << " " << (unsigned long)ClassStore <<
262 " " << size << "\n";
263}
264
265void FCLIntArray::Report()
266{
267 cout << " " << Operation << " " << (unsigned long)ClassStore <<
268 " " << size << "\n";
269}
270
271void FreeCheck::Register(void* t, char* name)
272{
273 FCLClass* f = new FCLClass(t,name);
274 if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
275#ifdef REG_DEREG
276 cout << "Registering " << name << " " << (unsigned long)t << "\n";
277#endif
278}
279
280void FreeCheck::RegisterR(void* t, char* o, int s)
281{
282 FCLRealArray* f = new FCLRealArray(t,o,s);
283 if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
284#ifdef REG_DEREG
285 cout << o << " " << s << " " << (unsigned long)t << "\n";
286#endif
287}
288
289void FreeCheck::RegisterI(void* t, char* o, int s)
290{
291 FCLIntArray* f = new FCLIntArray(t,o,s);
292 if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
293#ifdef REG_DEREG
294 cout << o << " " << s << " " << (unsigned long)t << "\n";
295#endif
296}
297
298void FreeCheck::DeRegister(void* t, char* name)
299{
300 FreeCheckLink* last = 0;
301#ifdef REG_DEREG
302 cout << "Deregistering " << name << " " << (unsigned long)t << "\n";
303#endif
304 for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
305 {
306 if (fcl->ClassStore==t)
307 {
308 if (last) last->next = fcl->next; else next = fcl->next;
309 delete fcl; return;
310 }
311 last = fcl;
312 }
313 cout << "\nRequest to delete non-existent object of class and location:\n";
314 cout << " " << name << " " << (unsigned long)t << "\n";
315 BadDelete++;
316 Tracer::PrintTrace();
317 cout << "\n";
318}
319
320void FreeCheck::DeRegisterR(void* t, char* o, int s)
321{
322 FreeCheckLink* last = 0;
323#ifdef REG_DEREG
324 cout << o << " " << s << " " << (unsigned long)t << "\n";
325#endif
326 for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
327 {
328 if (fcl->ClassStore==t)
329 {
330 if (last) last->next = fcl->next; else next = fcl->next;
331 if (s >= 0 && ((FCLRealArray*)fcl)->size != s)
332 {
333 cout << "\nArray sizes do not agree:\n";
334 cout << " " << o << " " << (unsigned long)t
335 << " " << ((FCLRealArray*)fcl)->size << " " << s << "\n";
336 Tracer::PrintTrace();
337 cout << "\n";
338 }
339 delete fcl; return;
340 }
341 last = fcl;
342 }
343 cout << "\nRequest to delete non-existent real array:\n";
344 cout << " " << o << " " << (unsigned long)t << " " << s << "\n";
345 BadDelete++;
346 Tracer::PrintTrace();
347 cout << "\n";
348}
349
350void FreeCheck::DeRegisterI(void* t, char* o, int s)
351{
352 FreeCheckLink* last = 0;
353#ifdef REG_DEREG
354 cout << o << " " << s << " " << (unsigned long)t << "\n";
355#endif
356 for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
357 {
358 if (fcl->ClassStore==t)
359 {
360 if (last) last->next = fcl->next; else next = fcl->next;
361 if (s >= 0 && ((FCLIntArray*)fcl)->size != s)
362 {
363 cout << "\nArray sizes do not agree:\n";
364 cout << " " << o << " " << (unsigned long)t
365 << " " << ((FCLIntArray*)fcl)->size << " " << s << "\n";
366 Tracer::PrintTrace();
367 cout << "\n";
368 }
369 delete fcl; return;
370 }
371 last = fcl;
372 }
373 cout << "\nRequest to delete non-existent int array:\n";
374 cout << " " << o << " " << (unsigned long)t << " " << s << "\n";
375 BadDelete++;
376 Tracer::PrintTrace();
377 cout << "\n";
378}
379
380void FreeCheck::Status()
381{
382 if (next)
383 {
384 cout << "\nObjects of the following classes remain undeleted:\n";
385 for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next) fcl->Report();
386 cout << "\n";
387 }
388 else cout << "\nNo objects remain undeleted\n\n";
389 if (BadDelete)
390 {
391 cout << "\nThere were " << BadDelete <<
392 " requests to delete non-existent items\n\n";
393 }
394}
395
396#endif // end of DO_FREE_CHECK
397
398// derived exception bodies
399
400Logic_error::Logic_error(const char* a_what) : BaseException()
401{
402 Select = BaseException::Select;
403 AddMessage("Logic error:- "); AddMessage(a_what);
404 if (a_what) Tracer::AddTrace();
405}
406
407Runtime_error::Runtime_error(const char* a_what)
408 : BaseException()
409{
410 Select = BaseException::Select;
411 AddMessage("Runtime error:- "); AddMessage(a_what);
412 if (a_what) Tracer::AddTrace();
413}
414
415Domain_error::Domain_error(const char* a_what) : Logic_error()
416{
417 Select = BaseException::Select;
418 AddMessage("domain error\n"); AddMessage(a_what);
419 if (a_what) Tracer::AddTrace();
420}
421
422Invalid_argument::Invalid_argument(const char* a_what) : Logic_error()
423{
424 Select = BaseException::Select;
425 AddMessage("invalid argument\n"); AddMessage(a_what);
426 if (a_what) Tracer::AddTrace();
427}
428
429Length_error::Length_error(const char* a_what) : Logic_error()
430{
431 Select = BaseException::Select;
432 AddMessage("length error\n"); AddMessage(a_what);
433 if (a_what) Tracer::AddTrace();
434}
435
436Out_of_range::Out_of_range(const char* a_what) : Logic_error()
437{
438 Select = BaseException::Select;
439 AddMessage("out of range\n"); AddMessage(a_what);
440 if (a_what) Tracer::AddTrace();
441}
442
443//Bad_cast::Bad_cast(const char* a_what) : Logic_error()
444//{
445// Select = BaseException::Select;
446// AddMessage("bad cast\n"); AddMessage(a_what);
447// if (a_what) Tracer::AddTrace();
448//}
449
450//Bad_typeid::Bad_typeid(const char* a_what) : Logic_error()
451//{
452// Select = BaseException::Select;
453// AddMessage("bad type id.\n"); AddMessage(a_what);
454// if (a_what) Tracer::AddTrace();
455//}
456
457Range_error::Range_error(const char* a_what) : Runtime_error()
458{
459 Select = BaseException::Select;
460 AddMessage("range error\n"); AddMessage(a_what);
461 if (a_what) Tracer::AddTrace();
462}
463
464Overflow_error::Overflow_error(const char* a_what) : Runtime_error()
465{
466 Select = BaseException::Select;
467 AddMessage("overflow error\n"); AddMessage(a_what);
468 if (a_what) Tracer::AddTrace();
469}
470
471Bad_alloc::Bad_alloc(const char* a_what) : BaseException()
472{
473 Select = BaseException::Select;
474 AddMessage("bad allocation\n"); AddMessage(a_what);
475 if (a_what) Tracer::AddTrace();
476}
477
478
479
480
481unsigned long Logic_error::Select;
482unsigned long Runtime_error::Select;
483unsigned long Domain_error::Select;
484unsigned long Invalid_argument::Select;
485unsigned long Length_error::Select;
486unsigned long Out_of_range::Select;
487//unsigned long Bad_cast::Select;
488//unsigned long Bad_typeid::Select;
489unsigned long Range_error::Select;
490unsigned long Overflow_error::Select;
491unsigned long Bad_alloc::Select;
492
493#ifdef use_namespace
494}
495#endif
496
497
498///@}
499
Note: See TracBrowser for help on using the repository browser.