home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / shells / bashsrc.zoo / unwind_prot.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-05  |  4.7 KB  |  195 lines

  1. /* I can't stand it anymore!  Please can't we just write the
  2.    whole Unix system in lisp or something? */
  3.  
  4. /* Copyright (C) 1987,1989 Free Software Foundation, Inc.
  5.  
  6. This file is part of GNU Bash, the Bourne Again SHell.
  7.  
  8. Bash is free software; you can redistribute it and/or modify it under
  9. the terms of the GNU General Public License as published by the Free
  10. Software Foundation; either version 1, or (at your option) any later
  11. version.
  12.  
  13. Bash is distributed in the hope that it will be useful, but WITHOUT ANY
  14. 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 along
  19. with Bash; see the file COPYING.  If not, write to the Free Software
  20. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  21.  
  22. /* **************************************************************** */
  23. /*                                    */
  24. /*              Unwind Protection Scheme for Bash            */
  25. /*                                    */
  26. /* **************************************************************** */
  27.  
  28. #include <sys/signal.h>
  29. #include "config.h"
  30. #include "general.h"
  31.  
  32. /* If CLEANUP is null, then ARG contains a tag to throw back to. */
  33. typedef struct _uwp {
  34.   struct _uwp *next;
  35.   Function *cleanup;
  36.   char *arg;
  37. } UNWIND_ELT;
  38.  
  39. static UNWIND_ELT *unwind_protect_list = (UNWIND_ELT *)NULL;
  40.  
  41. /* Run a function without interrupts. */
  42. without_interrupts (function, arg1, arg2)
  43.      Function *function;
  44.      char *arg1, *arg2;
  45. {
  46.   SigHandler *old_int;
  47.  
  48.   old_int = (SigHandler *)signal (SIGINT, SIG_IGN);
  49.   (*function)(arg1, arg2);
  50.   signal (SIGINT, old_int);
  51. }
  52.  
  53. /* Start the beginning of a region. */
  54. begin_unwind_frame (tag)
  55.      char *tag;
  56. {
  57.   add_unwind_protect ((Function *)NULL, tag);
  58. }
  59.  
  60. /* Discard the unwind protects back to TAG. */
  61. discard_unwind_frame (tag)
  62.      char *tag;
  63. {
  64.   int unwind_frame_discard_internal ();
  65.  
  66.   without_interrupts (unwind_frame_discard_internal, tag);
  67. }
  68.  
  69. /* Run the unwind protects back to TAG. */
  70. run_unwind_frame (tag)
  71.      char *tag;
  72. {
  73.   int unwind_frame_run_internal ();
  74.   without_interrupts (unwind_frame_run_internal, tag);
  75. }
  76.  
  77. /* Add the function CLEANUP with ARG to the list of unwindable things. */
  78. add_unwind_protect (cleanup, arg)
  79.      Function *cleanup;
  80.      char *arg;
  81. {
  82.   int add_unwind_protect_internal ();
  83.   without_interrupts (add_unwind_protect_internal, cleanup, arg);
  84. }
  85.  
  86. /* Remove the top unwind protect from the list. */
  87. remove_unwind_protect ()
  88. {
  89.   int remove_unwind_protect_internal ();
  90.   without_interrupts (remove_unwind_protect_internal);
  91. }
  92.  
  93. /* Run the list of cleanup functions in unwind_protect_list. */
  94. run_unwind_protects ()
  95. {
  96.   int run_unwind_protects_internal ();
  97.   without_interrupts (run_unwind_protects_internal);
  98. }
  99.  
  100. /* **************************************************************** */
  101. /*                                    */
  102. /*                        The Actual Functions                         */
  103. /*                                    */
  104. /* **************************************************************** */
  105.  
  106. add_unwind_protect_internal (cleanup, arg)
  107.      Function *cleanup;
  108.      char *arg;
  109. {
  110.   UNWIND_ELT *elt;
  111.  
  112.   elt = (UNWIND_ELT *)xmalloc (sizeof (UNWIND_ELT));
  113.   elt->cleanup = cleanup;
  114.   elt->arg = arg;
  115.   elt->next = unwind_protect_list;
  116.   unwind_protect_list = elt;
  117. }
  118.  
  119. remove_unwind_protect_internal ()
  120. {
  121.   UNWIND_ELT *elt = unwind_protect_list;
  122.  
  123.   if (elt)
  124.     {
  125.       unwind_protect_list = unwind_protect_list->next;
  126.       free (elt);
  127.     }
  128. }
  129.  
  130. run_unwind_protects_internal ()
  131. {
  132.   UNWIND_ELT *t, *elt = unwind_protect_list;
  133.  
  134.   while (elt)
  135.     {
  136.       /* This function can be run at strange times, like when unwinding
  137.      the entire world of unwind protects.  Thus, we may come across
  138.      an element which is simply a label for a catch frame.  Don't call
  139.      the non-existant function. */
  140.       if (elt->cleanup)
  141.     (*(elt->cleanup)) (elt->arg);
  142.  
  143.       t = elt;
  144.       elt = elt->next;
  145.       free (t);
  146.     }
  147.   unwind_protect_list = elt;
  148. }
  149.  
  150. unwind_frame_discard_internal (tag)
  151.      char *tag;
  152. {
  153.   UNWIND_ELT *elt;
  154.  
  155.   while (elt = unwind_protect_list)
  156.     {
  157.       unwind_protect_list = unwind_protect_list->next;
  158.       if (!elt->cleanup && strcmp (elt->arg, tag) == 0)
  159.     {
  160.       free (elt);
  161.       break;
  162.     }
  163.       else
  164.     free (elt);
  165.     }
  166. }
  167.  
  168. unwind_frame_run_internal (tag)
  169.      char *tag;
  170. {
  171.   UNWIND_ELT *elt;
  172.  
  173.   while (elt = unwind_protect_list)
  174.     {
  175.       unwind_protect_list = elt->next;
  176.  
  177.       /* If tag, then compare. */
  178.       if (!elt->cleanup)
  179.     {
  180.       if (strcmp (elt->arg, tag) == 0)
  181.         {
  182.           free (elt);
  183.           break;
  184.         }
  185.       free (elt);
  186.       continue;
  187.     }
  188.       else
  189.     {
  190.       (*(elt->cleanup)) (elt->arg);
  191.       free (elt);
  192.     }
  193.     }
  194. }
  195.