Mercurial > hg > xemacs-beta
comparison src/backtrace.h @ 428:3ecd8885ac67 r21-2-22
Import from CVS: tag r21-2-22
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:28:15 +0200 |
parents | |
children | 8de8e3f6228a |
comparison
equal
deleted
inserted
replaced
427:0a0253eac470 | 428:3ecd8885ac67 |
---|---|
1 /* The lisp stack. | |
2 Copyright (C) 1985, 1986, 1987, 1992, 1993 Free Software Foundation, Inc. | |
3 | |
4 This file is part of XEmacs. | |
5 | |
6 XEmacs is free software; you can redistribute it and/or modify it | |
7 under the terms of the GNU General Public License as published by the | |
8 Free Software Foundation; either version 2, or (at your option) any | |
9 later version. | |
10 | |
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with XEmacs; see the file COPYING. If not, write to | |
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
19 Boston, MA 02111-1307, USA. */ | |
20 | |
21 /* Synched up with: FSF 19.30. Contained redundantly in various C files | |
22 in FSFmacs. */ | |
23 | |
24 /* Authorship: | |
25 | |
26 FSF: Original version; a long time ago. | |
27 XEmacs: split out of some C files. (For some obscure reason, a header | |
28 file couldn't be used in FSF Emacs, but XEmacs doesn't have | |
29 that problem.) | |
30 Mly (probably) or JWZ: Some changes. | |
31 */ | |
32 | |
33 #ifndef _XEMACS_BACKTRACE_H_ | |
34 #define _XEMACS_BACKTRACE_H_ | |
35 | |
36 #include <setjmp.h> | |
37 | |
38 /* These definitions are used in eval.c and alloc.c */ | |
39 | |
40 struct backtrace | |
41 { | |
42 struct backtrace *next; | |
43 Lisp_Object *function; | |
44 Lisp_Object *args; /* Points to vector of args. */ | |
45 int nargs; /* Length of vector. | |
46 If nargs is UNEVALLED, args points to | |
47 slot holding list of unevalled args */ | |
48 int pdlcount; /* specpdl_depth () when invoked */ | |
49 char evalargs; | |
50 /* Nonzero means call value of debugger when done with this operation. */ | |
51 char debug_on_exit; | |
52 }; | |
53 | |
54 /* This structure helps implement the `catch' and `throw' control | |
55 structure. A struct catchtag contains all the information needed | |
56 to restore the state of the interpreter after a non-local jump. | |
57 | |
58 Handlers for error conditions (represented by `struct handler' | |
59 structures) just point to a catch tag to do the cleanup required | |
60 for their jumps. | |
61 | |
62 catchtag structures are chained together in the C calling stack; | |
63 the `next' member points to the next outer catchtag. | |
64 | |
65 A call like (throw TAG VAL) searches for a catchtag whose `tag' | |
66 member is TAG, and then unbinds to it. The `val' member is used to | |
67 hold VAL while the stack is unwound; `val' is returned as the value | |
68 of the catch form. | |
69 | |
70 All the other members are concerned with restoring the interpreter | |
71 state. */ | |
72 | |
73 struct catchtag | |
74 { | |
75 Lisp_Object tag; | |
76 Lisp_Object val; | |
77 struct catchtag *next; | |
78 struct gcpro *gcpro; | |
79 JMP_BUF jmp; | |
80 struct backtrace *backlist; | |
81 #if 0 /* FSFmacs */ | |
82 /* #### */ | |
83 struct handler *handlerlist; | |
84 #endif | |
85 int lisp_eval_depth; | |
86 int pdlcount; | |
87 #if 0 /* FSFmacs */ | |
88 /* This is the equivalent of async_timer_suppress_count. | |
89 We probably don't have to bother with this. */ | |
90 int poll_suppress_count; | |
91 #endif | |
92 }; | |
93 | |
94 /* Dynamic-binding-o-rama */ | |
95 | |
96 /* Structure for recording Lisp call stack for backtrace purposes. */ | |
97 | |
98 /* The special binding stack holds the outer values of variables while | |
99 they are bound by a function application or a let form, stores the | |
100 code to be executed for Lisp unwind-protect forms, and stores the C | |
101 functions to be called for record_unwind_protect. | |
102 | |
103 If func is non-zero, undoing this binding applies func to old_value; | |
104 This implements record_unwind_protect. | |
105 If func is zero and symbol is nil, undoing this binding evaluates | |
106 the list of forms in old_value; this implements Lisp's unwind-protect | |
107 form. | |
108 Otherwise, undoing this binding stores old_value as symbol's value; this | |
109 undoes the bindings made by a let form or function call. */ | |
110 | |
111 struct specbinding | |
112 { | |
113 Lisp_Object symbol; | |
114 Lisp_Object old_value; | |
115 Lisp_Object (*func) (Lisp_Object); /* for unwind-protect */ | |
116 }; | |
117 | |
118 #if 0 /* FSFmacs */ | |
119 /* #### */ | |
120 /* Everything needed to describe an active condition case. */ | |
121 struct handler | |
122 { | |
123 /* The handler clauses and variable from the condition-case form. */ | |
124 Lisp_Object handler; | |
125 Lisp_Object var; | |
126 /* Fsignal stores here the condition-case clause that applies, | |
127 and Fcondition_case thus knows which clause to run. */ | |
128 Lisp_Object chosen_clause; | |
129 | |
130 /* Used to effect the longjmp() out to the handler. */ | |
131 struct catchtag *tag; | |
132 | |
133 /* The next enclosing handler. */ | |
134 struct handler *next; | |
135 }; | |
136 | |
137 extern struct handler *handlerlist; | |
138 | |
139 #endif | |
140 | |
141 /* These are extern because GC needs to mark them */ | |
142 extern struct specbinding *specpdl; | |
143 extern struct specbinding *specpdl_ptr; | |
144 extern struct catchtag *catchlist; | |
145 extern struct backtrace *backtrace_list; | |
146 | |
147 /* Most callers should simply use specbind() and unbind_to(), but if | |
148 speed is REALLY IMPORTANT, you can use the faster macros below */ | |
149 void specbind_magic (Lisp_Object, Lisp_Object); | |
150 void grow_specpdl (size_t reserved); | |
151 void unbind_to_hairy (int); | |
152 extern int specpdl_size; | |
153 | |
154 /* Inline version of specbind(). | |
155 Use this instead of specbind() if speed is sufficiently important | |
156 to save the overhead of even a single function call. */ | |
157 #define SPECBIND(symbol_object, value_object) do { \ | |
158 Lisp_Object SB_symbol = (symbol_object); \ | |
159 Lisp_Object SB_newval = (value_object); \ | |
160 Lisp_Object SB_oldval; \ | |
161 struct Lisp_Symbol *SB_sym; \ | |
162 \ | |
163 SPECPDL_RESERVE (1); \ | |
164 \ | |
165 CHECK_SYMBOL (SB_symbol); \ | |
166 SB_sym = XSYMBOL (SB_symbol); \ | |
167 SB_oldval = SB_sym->value; \ | |
168 \ | |
169 if (!SYMBOL_VALUE_MAGIC_P (SB_oldval) || UNBOUNDP (SB_oldval)) \ | |
170 { \ | |
171 /* ### the following test will go away when we have a constant \ | |
172 symbol magic object */ \ | |
173 if (EQ (SB_symbol, Qnil) || \ | |
174 EQ (SB_symbol, Qt) || \ | |
175 SYMBOL_IS_KEYWORD (SB_symbol)) \ | |
176 reject_constant_symbols (SB_symbol, SB_newval, 0, \ | |
177 UNBOUNDP (SB_newval) ? \ | |
178 Qmakunbound : Qset); \ | |
179 \ | |
180 specpdl_ptr->symbol = SB_symbol; \ | |
181 specpdl_ptr->old_value = SB_oldval; \ | |
182 specpdl_ptr->func = 0; \ | |
183 specpdl_ptr++; \ | |
184 specpdl_depth_counter++; \ | |
185 \ | |
186 SB_sym->value = (SB_newval); \ | |
187 } \ | |
188 else \ | |
189 specbind_magic (SB_symbol, SB_newval); \ | |
190 } while (0) | |
191 | |
192 /* An even faster, but less safe inline version of specbind(). | |
193 Caller guarantees that: | |
194 - SYMBOL is a non-constant symbol (i.e. not Qnil, Qt, or keyword). | |
195 - specpdl_depth_counter >= specpdl_size. | |
196 Else we crash. */ | |
197 #define SPECBIND_FAST_UNSAFE(symbol_object, value_object) do { \ | |
198 Lisp_Object SFU_symbol = (symbol_object); \ | |
199 Lisp_Object SFU_newval = (value_object); \ | |
200 struct Lisp_Symbol *SFU_sym = XSYMBOL (SFU_symbol); \ | |
201 Lisp_Object SFU_oldval = SFU_sym->value; \ | |
202 if (!SYMBOL_VALUE_MAGIC_P (SFU_oldval) || UNBOUNDP (SFU_oldval)) \ | |
203 { \ | |
204 specpdl_ptr->symbol = SFU_symbol; \ | |
205 specpdl_ptr->old_value = SFU_oldval; \ | |
206 specpdl_ptr->func = 0; \ | |
207 specpdl_ptr++; \ | |
208 specpdl_depth_counter++; \ | |
209 \ | |
210 SFU_sym->value = (SFU_newval); \ | |
211 } \ | |
212 else \ | |
213 specbind_magic (SFU_symbol, SFU_newval); \ | |
214 } while (0) | |
215 | |
216 /* Request enough room for SIZE future entries on special binding stack */ | |
217 #define SPECPDL_RESERVE(size) do { \ | |
218 size_t SR_size = (size); \ | |
219 if (specpdl_depth() + SR_size >= specpdl_size) \ | |
220 grow_specpdl (SR_size); \ | |
221 } while (0) | |
222 | |
223 /* Inline version of unbind_to(). | |
224 Use this instead of unbind_to() if speed is sufficiently important | |
225 to save the overhead of even a single function call. | |
226 | |
227 Most of the time, unbind_to() is called only on ordinary | |
228 variables, so optimize for that. */ | |
229 #define UNBIND_TO_GCPRO(count, value) do { \ | |
230 int UNBIND_TO_count = (count); \ | |
231 while (specpdl_depth_counter != UNBIND_TO_count) \ | |
232 { \ | |
233 struct Lisp_Symbol *sym; \ | |
234 --specpdl_ptr; \ | |
235 --specpdl_depth_counter; \ | |
236 \ | |
237 if (specpdl_ptr->func != 0 || \ | |
238 ((sym = XSYMBOL (specpdl_ptr->symbol)), \ | |
239 SYMBOL_VALUE_MAGIC_P (sym->value))) \ | |
240 { \ | |
241 struct gcpro gcpro1; \ | |
242 GCPRO1 (value); \ | |
243 unbind_to_hairy (UNBIND_TO_count); \ | |
244 UNGCPRO; \ | |
245 break; \ | |
246 } \ | |
247 \ | |
248 sym->value = specpdl_ptr->old_value; \ | |
249 } \ | |
250 } while (0) | |
251 | |
252 /* A slightly faster inline version of unbind_to, | |
253 that doesn't offer GCPROing services. */ | |
254 #define UNBIND_TO(count) do { \ | |
255 int UNBIND_TO_count = (count); \ | |
256 while (specpdl_depth_counter != UNBIND_TO_count) \ | |
257 { \ | |
258 struct Lisp_Symbol *sym; \ | |
259 --specpdl_ptr; \ | |
260 --specpdl_depth_counter; \ | |
261 \ | |
262 if (specpdl_ptr->func != 0 || \ | |
263 ((sym = XSYMBOL (specpdl_ptr->symbol)), \ | |
264 SYMBOL_VALUE_MAGIC_P (sym->value))) \ | |
265 { \ | |
266 unbind_to_hairy (UNBIND_TO_count); \ | |
267 break; \ | |
268 } \ | |
269 \ | |
270 sym->value = specpdl_ptr->old_value; \ | |
271 } \ | |
272 } while (0) | |
273 | |
274 #ifdef ERROR_CHECK_TYPECHECK | |
275 #define CHECK_SPECBIND_VARIABLE assert (specpdl_ptr->func == 0) | |
276 #else | |
277 #define CHECK_SPECBIND_VARIABLE DO_NOTHING | |
278 #endif | |
279 | |
280 #if 0 | |
281 /* Unused. It's too hard to guarantee that the current bindings | |
282 contain only variables. */ | |
283 /* Another inline version of unbind_to(). VALUE is GC-protected. | |
284 Caller guarantees that: | |
285 - all of the elements on the binding stack are variable bindings. | |
286 Else we crash. */ | |
287 #define UNBIND_TO_GCPRO_VARIABLES_ONLY(count, value) do { \ | |
288 int UNBIND_TO_count = (count); \ | |
289 while (specpdl_depth_counter != UNBIND_TO_count) \ | |
290 { \ | |
291 struct Lisp_Symbol *sym; \ | |
292 --specpdl_ptr; \ | |
293 --specpdl_depth_counter; \ | |
294 \ | |
295 CHECK_SPECBIND_VARIABLE; \ | |
296 sym = XSYMBOL (specpdl_ptr->symbol); \ | |
297 if (!SYMBOL_VALUE_MAGIC_P (sym->value)) \ | |
298 sym->value = specpdl_ptr->old_value; \ | |
299 else \ | |
300 { \ | |
301 struct gcpro gcpro1; \ | |
302 GCPRO1 (value); \ | |
303 unbind_to_hairy (UNBIND_TO_count); \ | |
304 UNGCPRO; \ | |
305 break; \ | |
306 } \ | |
307 } \ | |
308 } while (0) | |
309 #endif /* unused */ | |
310 | |
311 /* A faster, but less safe inline version of Fset(). | |
312 Caller guarantees that: | |
313 - SYMBOL is a non-constant symbol (i.e. not Qnil, Qt, or keyword). | |
314 Else we crash. */ | |
315 #define FSET_FAST_UNSAFE(sym, newval) do { \ | |
316 Lisp_Object FFU_sym = (sym); \ | |
317 Lisp_Object FFU_newval = (newval); \ | |
318 struct Lisp_Symbol *FFU_symbol = XSYMBOL (FFU_sym); \ | |
319 Lisp_Object FFU_oldval = FFU_symbol->value; \ | |
320 if (!SYMBOL_VALUE_MAGIC_P (FFU_oldval) || UNBOUNDP (FFU_oldval)) \ | |
321 FFU_symbol->value = FFU_newval; \ | |
322 else \ | |
323 Fset (FFU_sym, FFU_newval); \ | |
324 } while (0) | |
325 | |
326 #endif /* _XEMACS_BACKTRACE_H_ */ |