source: nanovis/trunk/newmat11/myexcept.cpp @ 4794

Last change on this file since 4794 was 2096, checked in by ldelgass, 9 years ago

Normalize line endings, set eol-style to native on *.cpp, *.h files

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