source: trunk/essentials/app-shells/bash/unwind_prot.c@ 3506

Last change on this file since 3506 was 3231, checked in by bird, 19 years ago

eol style.

  • Property svn:eol-style set to native
File size: 7.8 KB
RevLine 
[3228]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-2002 Free Software Foundation, Inc.
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
8Bash is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 2, or (at your option) any later
11version.
12
13Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License along
19with Bash; see the file COPYING. If not, write to the Free Software
20Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
21
22/* **************************************************************** */
23/* */
24/* Unwind Protection Scheme for Bash */
25/* */
26/* **************************************************************** */
27#include "config.h"
28
29#include "bashtypes.h"
30#include "bashansi.h"
31
32#if defined (HAVE_UNISTD_H)
33# include <unistd.h>
34#endif
35
36#if STDC_HEADERS
37# include <stddef.h>
38#endif
39
40#ifndef offsetof
41# define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
42#endif
43
44#include "command.h"
45#include "general.h"
46#include "unwind_prot.h"
47#include "quit.h"
48#include "sig.h"
49
50/* Structure describing a saved variable and the value to restore it to. */
51typedef struct {
52 char *variable;
53 int size;
54 char desired_setting[1]; /* actual size is `size' */
55} SAVED_VAR;
56
57/* If HEAD.CLEANUP is null, then ARG.V contains a tag to throw back to.
58 If HEAD.CLEANUP is restore_variable, then SV.V contains the saved
59 variable. Otherwise, call HEAD.CLEANUP (ARG.V) to clean up. */
60typedef union uwp {
61 struct uwp_head {
62 union uwp *next;
63 Function *cleanup;
64 } head;
65 struct {
66 struct uwp_head uwp_head;
67 char *v;
68 } arg;
69 struct {
70 struct uwp_head uwp_head;
71 SAVED_VAR v;
72 } sv;
73} UNWIND_ELT;
74
75
76extern int interrupt_immediately;
77
78static void without_interrupts __P((VFunction *, char *, char *));
79static void unwind_frame_discard_internal __P((char *, char *));
80static void unwind_frame_run_internal __P((char *, char *));
81static void add_unwind_protect_internal __P((Function *, char *));
82static void remove_unwind_protect_internal __P((char *, char *));
83static void run_unwind_protects_internal __P((char *, char *));
84static void clear_unwind_protects_internal __P((char *, char *));
85static inline void restore_variable __P((SAVED_VAR *));
86static void unwind_protect_mem_internal __P((char *, char *));
87
88static UNWIND_ELT *unwind_protect_list = (UNWIND_ELT *)NULL;
89
90#define uwpalloc(elt) (elt) = (UNWIND_ELT *)xmalloc (sizeof (UNWIND_ELT))
91#define uwpfree(elt) free(elt)
92
93/* Run a function without interrupts. This relies on the fact that the
94 FUNCTION cannot change the value of interrupt_immediately. (I.e., does
95 not call QUIT (). */
96static void
97without_interrupts (function, arg1, arg2)
98 VFunction *function;
99 char *arg1, *arg2;
100{
101 int old_interrupt_immediately;
102
103 old_interrupt_immediately = interrupt_immediately;
104 interrupt_immediately = 0;
105
106 (*function)(arg1, arg2);
107
108 interrupt_immediately = old_interrupt_immediately;
109}
110
111/* Start the beginning of a region. */
112void
113begin_unwind_frame (tag)
114 char *tag;
115{
116 add_unwind_protect ((Function *)NULL, tag);
117}
118
119/* Discard the unwind protects back to TAG. */
120void
121discard_unwind_frame (tag)
122 char *tag;
123{
124 if (unwind_protect_list)
125 without_interrupts (unwind_frame_discard_internal, tag, (char *)NULL);
126}
127
128/* Run the unwind protects back to TAG. */
129void
130run_unwind_frame (tag)
131 char *tag;
132{
133 if (unwind_protect_list)
134 without_interrupts (unwind_frame_run_internal, tag, (char *)NULL);
135}
136
137/* Add the function CLEANUP with ARG to the list of unwindable things. */
138void
139add_unwind_protect (cleanup, arg)
140 Function *cleanup;