home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / octave-1.1.1p1-src.tgz / tar.out / fsf / octave / src / unwind-prot.cc < prev    next >
C/C++ Source or Header  |  1996-09-28  |  6KB  |  318 lines

  1. // unwind-prot.cc                                              -*- C++ -*-
  2. /*
  3.  
  4. Copyright (C) 1992, 1993, 1994, 1995 John W. Eaton
  5.  
  6. This file is part of Octave.
  7.  
  8. Octave is free software; you can redistribute it and/or modify it
  9. under the terms of the GNU General Public License as published by the
  10. Free Software Foundation; either version 2, or (at your option) any
  11. later version.
  12.  
  13. Octave is distributed in the hope that it will be useful, but WITHOUT
  14. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  16. for more details.
  17.  
  18. You should have received a copy of the GNU General Public License
  19. along with Octave; see the file COPYING.  If not, write to the Free
  20. Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  
  22. */
  23.  
  24. #ifdef HAVE_CONFIG_H
  25. #include "config.h"
  26. #endif
  27.  
  28. #include <stddef.h>
  29.  
  30. #include "SLStack.h"
  31.  
  32. #include "CMatrix.h"
  33.  
  34. #include "unwind-prot.h"
  35. #include "error.h"
  36. #include "utils.h"
  37.  
  38. unwind_elem::unwind_elem (void)
  39. {
  40.   unwind_elem_tag = 0;
  41.   unwind_elem_fptr = 0;
  42.   unwind_elem_ptr = 0;
  43. }
  44.  
  45. unwind_elem::unwind_elem (char *t)
  46. {
  47.   unwind_elem_tag = strsave (t);
  48.   unwind_elem_fptr = 0;
  49.   unwind_elem_ptr = 0;
  50. }
  51.  
  52. unwind_elem::unwind_elem (cleanup_func f, void *p)
  53. {
  54.   unwind_elem_tag = 0;
  55.   unwind_elem_fptr = f;
  56.   unwind_elem_ptr = p;
  57. }
  58.  
  59. unwind_elem::unwind_elem (const unwind_elem& el)
  60. {
  61.   unwind_elem_tag = strsave (el.unwind_elem_tag);
  62.   unwind_elem_fptr = el.unwind_elem_fptr;
  63.   unwind_elem_ptr = el.unwind_elem_ptr;
  64. }
  65.  
  66. unwind_elem::~unwind_elem (void)
  67. {
  68.   delete [] unwind_elem_tag;
  69. }
  70.  
  71. unwind_elem&
  72. unwind_elem::operator = (const unwind_elem& el)
  73. {
  74.   unwind_elem_tag = strsave (el.unwind_elem_tag);
  75.   unwind_elem_fptr = el.unwind_elem_fptr;
  76.   unwind_elem_ptr = el.unwind_elem_ptr;
  77.  
  78.   return *this;
  79. }
  80.  
  81. char *
  82. unwind_elem::tag (void)
  83. {
  84.   return unwind_elem_tag;
  85. }
  86.  
  87. cleanup_func
  88. unwind_elem::fptr (void)
  89. {
  90.   return unwind_elem_fptr;
  91. }
  92.  
  93. void *
  94. unwind_elem::ptr (void)
  95. {
  96.   return unwind_elem_ptr;
  97. }
  98.  
  99. static SLStack <unwind_elem> unwind_protect_list;
  100.  
  101. void
  102. add_unwind_protect (cleanup_func fptr, void *ptr)
  103. {
  104.   unwind_elem el (fptr, ptr);
  105.   unwind_protect_list.push (el);
  106. }
  107.  
  108. void
  109. run_unwind_protect (void)
  110. {
  111.   unwind_elem el = unwind_protect_list.pop ();
  112.  
  113.   cleanup_func f = el.fptr ();
  114.   if (f)
  115.     f (el.ptr ());
  116. }
  117.  
  118. void
  119. discard_unwind_protect (void)
  120. {
  121.   unwind_protect_list.pop ();
  122. }
  123.  
  124. void
  125. begin_unwind_frame (char *tag)
  126. {
  127.   unwind_elem elem (tag);
  128.   unwind_protect_list.push (elem);
  129. }
  130.  
  131. void
  132. run_unwind_frame (char *tag)
  133. {
  134.   while (! unwind_protect_list.empty ())
  135.     {
  136.       unwind_elem el = unwind_protect_list.pop ();
  137.  
  138.       cleanup_func f = el.fptr ();
  139.       if (f)
  140.     f (el.ptr ());
  141.  
  142.       char *t = el.tag ();
  143.       if (t && strcmp (t, tag) == 0)
  144.     break;
  145.     }
  146. }
  147.  
  148. void
  149. discard_unwind_frame (char *tag)
  150. {
  151.   while (! unwind_protect_list.empty ())
  152.     {
  153.       unwind_elem el = unwind_protect_list.pop ();
  154.       char *t = el.tag ();
  155.       if (t && strcmp (t, tag) == 0)
  156.     break;
  157.     }
  158. }
  159.  
  160. void
  161. run_all_unwind_protects (void)
  162. {
  163.   while (! unwind_protect_list.empty ())
  164.     {
  165.       unwind_elem el = unwind_protect_list.pop ();
  166.  
  167.       cleanup_func f = el.fptr ();
  168.       if (f)
  169.     f (el.ptr ());
  170.     }
  171. }
  172.  
  173. void
  174. discard_all_unwind_protects (void)
  175. {
  176.   unwind_protect_list.clear ();
  177. }
  178.  
  179. void
  180. matrix_cleanup (void *m)
  181. {
  182.   delete [] (double *) m;
  183. }
  184.  
  185. void
  186. complex_matrix_cleanup (void *cm)
  187. {
  188.   delete [] (ComplexMatrix *) cm;
  189. }
  190.  
  191. class saved_variable
  192. {
  193.  public:
  194.   enum var_type { integer, generic_ptr, generic };
  195.  
  196.   saved_variable (void);
  197.   saved_variable (int *p, int v);
  198.   saved_variable (void **p, void *v);
  199.   saved_variable (void *p, void *v, size_t sz);
  200.   ~saved_variable (void);
  201.  
  202.   void restore_value (void);
  203.  
  204.  private:
  205.   union
  206.     {
  207.       int *ptr_to_int;
  208.       void *gen_ptr;
  209.       void **ptr_to_gen_ptr;
  210.     };
  211.  
  212.   union
  213.     {
  214.       int int_value;
  215.       void *gen_ptr_value;
  216.     };
  217.  
  218.   var_type type_tag;
  219.   size_t size;
  220. };
  221.  
  222. saved_variable::saved_variable (void)
  223. {
  224.   gen_ptr = 0;
  225.   gen_ptr_value = 0;
  226.   type_tag = generic;
  227.   size = 0;
  228. }
  229.  
  230. saved_variable::saved_variable (int *p, int v)
  231. {
  232.   type_tag = integer;
  233.   ptr_to_int = p;
  234.   int_value = v;
  235.   size = sizeof (int);
  236. }
  237.  
  238. saved_variable::saved_variable (void **p, void *v)
  239. {
  240.   type_tag = generic_ptr;
  241.   ptr_to_gen_ptr = p;
  242.   gen_ptr_value = v;
  243.   size = sizeof (void *);
  244. }
  245.  
  246. saved_variable::saved_variable (void *p, void *v, size_t sz)
  247. {
  248.   gen_ptr = v;
  249.   gen_ptr_value = new char [sz];
  250.   memcpy (gen_ptr_value, v, sz);
  251.   size = sz;
  252. }
  253.  
  254. saved_variable::~saved_variable (void)
  255. {
  256.   if (type_tag == generic)
  257.     delete [] gen_ptr_value;
  258. }
  259.  
  260. void
  261. saved_variable::restore_value (void)
  262. {
  263.   switch (type_tag)
  264.     {
  265.     case integer:
  266.       *ptr_to_int = int_value;
  267.       break;
  268.  
  269.     case generic_ptr:
  270.       *ptr_to_gen_ptr = gen_ptr_value;
  271.       break;
  272.  
  273.     case generic:
  274.       memcpy (gen_ptr, gen_ptr_value, size);
  275.       break;
  276.  
  277.     default:
  278.       panic_impossible ();
  279.       break;
  280.     }
  281. }
  282.  
  283. static void
  284. restore_saved_variable (void *s)
  285. {
  286.   saved_variable *sv = (saved_variable *) s;
  287.   sv->restore_value ();
  288.   delete sv;
  289. }
  290.  
  291. void
  292. unwind_protect_int_internal (int *ptr, int value)
  293. {
  294.   saved_variable *s = new saved_variable (ptr, value);
  295.   add_unwind_protect (restore_saved_variable, (void *) s);
  296. }
  297.  
  298. void
  299. unwind_protect_ptr_internal (void **ptr, void *value)
  300. {
  301.   saved_variable *s = new saved_variable (ptr, value);
  302.   add_unwind_protect (restore_saved_variable, (void *) s);
  303. }
  304.  
  305. void
  306. unwind_protect_var_internal (void *ptr, void *value, size_t size)
  307. {
  308.   saved_variable *s = new saved_variable (ptr, value, size);
  309.   add_unwind_protect (restore_saved_variable, (void *) s);
  310. }
  311.  
  312. /*
  313. ;;; Local Variables: ***
  314. ;;; mode: C++ ***
  315. ;;; page-delimiter: "^/\\*" ***
  316. ;;; End: ***
  317. */
  318.