Commit | Line | Data |
---|---|---|
9ede013f AW |
1 | /* classes: h_files */ |
2 | ||
3 | #ifndef SCM_DYNSTACK_H | |
4 | #define SCM_DYNSTACK_H | |
5 | ||
98eaef1b | 6 | /* Copyright (C) 2012, 2013 Free Software Foundation, Inc. |
9ede013f AW |
7 | * |
8 | * This library is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public License | |
10 | * as published by the Free Software Foundation; either version 3 of | |
11 | * the License, or (at your option) any later version. | |
12 | * | |
13 | * This library is distributed in the hope that it will be useful, but | |
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | * Lesser General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU Lesser General Public | |
19 | * License along with this library; if not, write to the Free Software | |
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
21 | * 02110-1301 USA | |
22 | */ | |
23 | ||
24 | \f | |
25 | ||
26 | #include "libguile/__scm.h" | |
9ede013f AW |
27 | |
28 | \f | |
29 | ||
30 | typedef struct | |
31 | { | |
32 | scm_t_bits *base; | |
33 | scm_t_bits *top; | |
34 | scm_t_bits *limit; | |
35 | } scm_t_dynstack; | |
36 | ||
37 | \f | |
38 | ||
39 | /* Items on the dynstack are preceded by two-word headers, giving the | |
40 | offset of the preceding item (or 0 if there is none) and the type, | |
41 | flags, and length of the following dynstack entry, in words. In | |
42 | addition, there is a "null header" at the top of the stack, | |
43 | indicating the length of the previous item, but with a tag of zero. | |
44 | ||
45 | For example, consider an empty dynstack, with a capacity of 6 words: | |
46 | ||
47 | +----------+----------+ + | |
48 | |prev=0 |tag=0 | | | |
49 | +----------+----------+ + | |
50 | ^base ^top limit^ | |
51 | ||
52 | Now we evaluate (dynamic-wind enter thunk leave). That will result | |
53 | in a dynstack of: | |
54 | ||
55 | / the len=2 words \ | |
56 | +----------+----------+----------+----------+----------+----------+ | |
57 | |prev=0 |tag:len=2 |enter |leave |prev=4 |tag=0 | | |
58 | +----------+----------+----------+----------+----------+----------+ | |
59 | ^base top,limit^ | |
60 | ||
61 | The tag is a combination of the type of the dynstack item, some flags | |
62 | associated with the item, and the length of the item. See | |
63 | SCM_MAKE_DYNSTACK_TAG below for the details. | |
64 | ||
65 | This arrangement makes it possible to have variable-length dynstack | |
66 | items, and yet be able to traverse them forwards or backwards. */ | |
67 | ||
68 | #define SCM_DYNSTACK_HEADER_LEN 2 | |
69 | ||
70 | #define SCM_DYNSTACK_PREV_OFFSET(top) ((top)[-2]) | |
71 | #define SCM_DYNSTACK_SET_PREV_OFFSET(top, offset) (top)[-2] = (offset) | |
72 | ||
73 | #define SCM_DYNSTACK_TAG(top) ((top)[-1]) | |
74 | #define SCM_DYNSTACK_SET_TAG(top, tag) (top)[-1] = (tag) | |
75 | ||
76 | typedef enum { | |
77 | SCM_DYNSTACK_TYPE_NONE = 0, | |
78 | SCM_DYNSTACK_TYPE_FRAME, | |
79 | SCM_DYNSTACK_TYPE_UNWINDER, | |
80 | SCM_DYNSTACK_TYPE_REWINDER, | |
98eaef1b | 81 | SCM_DYNSTACK_TYPE_WITH_FLUID, |
9ede013f AW |
82 | SCM_DYNSTACK_TYPE_PROMPT, |
83 | SCM_DYNSTACK_TYPE_DYNWIND, | |
84 | } scm_t_dynstack_item_type; | |
85 | ||
86 | #define SCM_DYNSTACK_TAG_TYPE_MASK 0xf | |
87 | #define SCM_DYNSTACK_TAG_FLAGS_MASK 0xf0 | |
88 | #define SCM_DYNSTACK_TAG_FLAGS_SHIFT 4 | |
89 | #define SCM_DYNSTACK_TAG_LEN_SHIFT 8 | |
90 | ||
91 | #define SCM_MAKE_DYNSTACK_TAG(type, flags, len) \ | |
92 | ((type) | (flags) | ((len) << SCM_DYNSTACK_TAG_LEN_SHIFT)) | |
93 | ||
94 | #define SCM_DYNSTACK_TAG_TYPE(tag) \ | |
95 | ((tag) & SCM_DYNSTACK_TAG_TYPE_MASK) | |
96 | #define SCM_DYNSTACK_TAG_FLAGS(tag) \ | |
97 | ((tag) & SCM_DYNSTACK_TAG_FLAGS_MASK) | |
98 | #define SCM_DYNSTACK_TAG_LEN(tag) \ | |
99 | ((tag) >> SCM_DYNSTACK_TAG_LEN_SHIFT) | |
100 | ||
101 | #define SCM_DYNSTACK_PREV(top) \ | |
102 | (SCM_DYNSTACK_PREV_OFFSET (top) \ | |
103 | ? ((top) - SCM_DYNSTACK_PREV_OFFSET (top)) : NULL) | |
104 | #define SCM_DYNSTACK_NEXT(top) \ | |
105 | (SCM_DYNSTACK_TAG (top) \ | |
106 | ? ((top) + SCM_DYNSTACK_TAG_LEN (SCM_DYNSTACK_TAG (top)) \ | |
107 | + SCM_DYNSTACK_HEADER_LEN) \ | |
108 | : NULL) | |
109 | ||
110 | #define SCM_DYNSTACK_FIRST(dynstack) \ | |
111 | ((dynstack)->base + SCM_DYNSTACK_HEADER_LEN) | |
112 | ||
113 | #define SCM_DYNSTACK_CAPACITY(dynstack) \ | |
114 | ((dynstack)->limit - (dynstack)->base) | |
115 | #define SCM_DYNSTACK_SPACE(dynstack) \ | |
116 | ((dynstack)->limit - (dynstack)->top) | |
117 | #define SCM_DYNSTACK_HEIGHT(dynstack) \ | |
118 | ((dynstack)->top - (dynstack)->base) | |
119 | ||
120 | #define SCM_DYNSTACK_HAS_SPACE(dynstack, n) \ | |
121 | (SCM_DYNSTACK_SPACE (dynstack) >= n + SCM_DYNSTACK_HEADER_LEN) | |
122 | ||
123 | typedef enum { | |
124 | SCM_F_DYNSTACK_FRAME_REWINDABLE = (1 << SCM_DYNSTACK_TAG_FLAGS_SHIFT) | |
125 | } scm_t_dynstack_frame_flags; | |
126 | ||
127 | typedef enum { | |
128 | SCM_F_DYNSTACK_WINDER_EXPLICIT = (1 << SCM_DYNSTACK_TAG_FLAGS_SHIFT) | |
129 | } scm_t_dynstack_winder_flags; | |
130 | ||
131 | typedef enum { | |
c6cd692f AW |
132 | SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY = (1 << SCM_DYNSTACK_TAG_FLAGS_SHIFT), |
133 | SCM_F_DYNSTACK_PROMPT_PUSH_NARGS = (2 << SCM_DYNSTACK_TAG_FLAGS_SHIFT) | |
9ede013f AW |
134 | } scm_t_dynstack_prompt_flags; |
135 | ||
136 | typedef void (*scm_t_guard) (void *); | |
137 | ||
138 | ||
139 | \f | |
140 | ||
141 | /* Pushing and popping entries on the dynamic stack. */ | |
142 | ||
143 | SCM_INTERNAL void scm_dynstack_push_frame (scm_t_dynstack *, | |
144 | scm_t_dynstack_frame_flags); | |
145 | SCM_INTERNAL void scm_dynstack_push_rewinder (scm_t_dynstack *, | |
146 | scm_t_dynstack_winder_flags, | |
147 | scm_t_guard, void *); | |
148 | SCM_INTERNAL void scm_dynstack_push_unwinder (scm_t_dynstack *, | |
149 | scm_t_dynstack_winder_flags, | |
150 | scm_t_guard, void *); | |
98eaef1b AW |
151 | SCM_INTERNAL void scm_dynstack_push_fluid (scm_t_dynstack *, |
152 | SCM fluid, SCM value, | |
153 | SCM dynamic_state); | |
9ede013f AW |
154 | SCM_INTERNAL void scm_dynstack_push_prompt (scm_t_dynstack *, |
155 | scm_t_dynstack_prompt_flags, | |
156 | SCM key, | |
0bca90aa AW |
157 | scm_t_ptrdiff fp_offset, |
158 | scm_t_ptrdiff sp_offset, | |
159 | scm_t_uint32 *ip, | |
9d381ba4 | 160 | scm_i_jmp_buf *registers); |
9ede013f AW |
161 | SCM_INTERNAL void scm_dynstack_push_dynwind (scm_t_dynstack *, |
162 | SCM enter, SCM leave); | |
163 | ||
164 | SCM_INTERNAL void scm_dynstack_pop (scm_t_dynstack *); | |
165 | ||
166 | ||
167 | \f | |
168 | ||
169 | /* Capturing, winding, and unwinding. */ | |
170 | ||
171 | SCM_INTERNAL scm_t_dynstack* scm_dynstack_capture_all (scm_t_dynstack *dynstack); | |
172 | SCM_INTERNAL scm_t_dynstack* scm_dynstack_capture (scm_t_dynstack *dynstack, | |
173 | scm_t_bits *item); | |
174 | ||
175 | SCM_INTERNAL void scm_dynstack_wind_1 (scm_t_dynstack *, scm_t_bits *); | |
176 | SCM_INTERNAL scm_t_bits scm_dynstack_unwind_1 (scm_t_dynstack *); | |
177 | ||
178 | SCM_INTERNAL void scm_dynstack_wind (scm_t_dynstack *, scm_t_bits *); | |
179 | SCM_INTERNAL void scm_dynstack_unwind (scm_t_dynstack *, scm_t_bits *); | |
180 | ||
9d381ba4 AW |
181 | |
182 | \f | |
183 | ||
184 | /* Miscellany. */ | |
185 | ||
9ede013f AW |
186 | SCM_INTERNAL scm_t_bits* scm_dynstack_unwind_fork (scm_t_dynstack *, |
187 | scm_t_dynstack *); | |
188 | ||
189 | SCM_INTERNAL void scm_dynstack_unwind_frame (scm_t_dynstack *); | |
98eaef1b AW |
190 | SCM_INTERNAL void scm_dynstack_unwind_fluid (scm_t_dynstack *dynstack, |
191 | SCM dynamic_state); | |
9ede013f | 192 | |
9ede013f | 193 | SCM_INTERNAL scm_t_bits* scm_dynstack_find_prompt (scm_t_dynstack *, SCM, |
9d381ba4 | 194 | scm_t_dynstack_prompt_flags *, |
0bca90aa AW |
195 | scm_t_ptrdiff *, |
196 | scm_t_ptrdiff *, | |
197 | scm_t_uint32 **, | |
9d381ba4 | 198 | scm_i_jmp_buf **); |
9ede013f | 199 | |
9d381ba4 AW |
200 | SCM_INTERNAL void scm_dynstack_wind_prompt (scm_t_dynstack *, scm_t_bits *, |
201 | scm_t_ptrdiff, scm_i_jmp_buf *); | |
9ede013f AW |
202 | |
203 | ||
204 | #endif /* SCM_DYNSTACK_H */ | |
205 | ||
206 | /* | |
207 | Local Variables: | |
208 | c-file-style: "gnu" | |
209 | End: | |
210 | */ |