Mercurial > hg > xemacs-beta
comparison src/specifier.h @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | 9f59509498e1 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:376386a54a3c |
---|---|
1 /* Generic specifier list implementation | |
2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois. | |
3 Copyright (C) 1995 Ben Wing | |
4 | |
5 This file is part of XEmacs. | |
6 | |
7 XEmacs is free software; you can redistribute it and/or modify it | |
8 under the terms of the GNU General Public License as published by the | |
9 Free Software Foundation; either version 2, or (at your option) any | |
10 later version. | |
11 | |
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with XEmacs; see the file COPYING. If not, write to | |
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 Boston, MA 02111-1307, USA. */ | |
21 | |
22 /* Synched up with: Not in FSF. */ | |
23 | |
24 #ifndef _XEMACS_SPECIFIER_H_ | |
25 #define _XEMACS_SPECIFIER_H_ | |
26 | |
27 struct specifier_methods | |
28 { | |
29 CONST char *name; | |
30 Lisp_Object predicate_symbol; | |
31 | |
32 /* Implementation specific methods: */ | |
33 | |
34 /* #### Document me */ | |
35 /* Create method */ | |
36 void (*create_method) (Lisp_Object specifier); | |
37 /* Mark method */ | |
38 void (*mark_method) (Lisp_Object specifier, void (*markobj) (Lisp_Object)); | |
39 /* Equal method */ | |
40 int (*equal_method) (Lisp_Object sp1, Lisp_Object sp2, int depth); | |
41 /* Hash method */ | |
42 unsigned long (*hash_method) (Lisp_Object specifier, int depth); | |
43 | |
44 /* Validate method: Given an instantiator, verify that it's | |
45 valid for this specifier type. If not, signal an error. | |
46 | |
47 If this functions is not present, all instantiators are | |
48 considered valid. */ | |
49 void (*validate_method) (Lisp_Object instantiator); | |
50 | |
51 /* Validate-matchspec method: Given a matchspec, verify that it's | |
52 valid for this specifier type. If not, signal an error. | |
53 | |
54 If this functions is not present, *no* matchspecs are considered | |
55 valid. Note that this differs from validate_method(). */ | |
56 void (*validate_matchspec_method) (Lisp_Object matchspec); | |
57 | |
58 /* Instantiate method */ | |
59 Lisp_Object (*instantiate_method) (Lisp_Object specifier, | |
60 Lisp_Object matchspec, | |
61 Lisp_Object domain, | |
62 Lisp_Object instantiator, | |
63 /* always an integer, but encapsulated | |
64 as a Lisp_Object so it can be called | |
65 from call_with_suspended_errors() */ | |
66 Lisp_Object depth); | |
67 /* Going-to-add method: Called when an instantiator is about | |
68 to be added to a specifier. This function can specify | |
69 that different instantiators should be used instead by | |
70 returning an inst-list (possibly containing zero elements). | |
71 If the instantiator is fine as-is, return Qt. The | |
72 instantiator has been copied with copy-tree, so feel | |
73 free to reuse parts of it to create a new instantiator. | |
74 The tag-set, however, is not copied and is not canonicalized | |
75 (that will be done on the result of this function). | |
76 */ | |
77 Lisp_Object (*going_to_add_method) (Lisp_Object specifier, | |
78 Lisp_Object locale, | |
79 Lisp_Object tag_set, | |
80 Lisp_Object instantiator); | |
81 /* After-change method */ | |
82 void (*after_change_method) (Lisp_Object specifier, | |
83 Lisp_Object locale); | |
84 | |
85 int extra_data_size; | |
86 }; | |
87 | |
88 struct Lisp_Specifier | |
89 { | |
90 struct lcrecord_header header; | |
91 struct specifier_methods *methods; | |
92 | |
93 /* we keep a chained list of all current specifiers, for GC cleanup | |
94 purposes. Do NOT mark through this, or specifiers will never | |
95 be GC'd. */ | |
96 Lisp_Object next_specifier; | |
97 | |
98 /* This is a straight list of instantiators. */ | |
99 Lisp_Object global_specs; | |
100 | |
101 /* These are all assoc lists where the key is type of object the | |
102 list represents (buffer, window, etc.) and the associated list is | |
103 the actual list of instantiators. */ | |
104 Lisp_Object device_specs; | |
105 Lisp_Object frame_specs; | |
106 /* window_specs is actually a key-assoc weak list. See specifier.c | |
107 for an explanation of why (it boils down to the fact that | |
108 dead windows can become live again through window configurations). | |
109 */ | |
110 Lisp_Object window_specs; | |
111 Lisp_Object buffer_specs; | |
112 | |
113 struct specifier_caching *caching; | |
114 Lisp_Object fallback; | |
115 /* type-specific extra data attached to a specifier */ | |
116 char data[1]; | |
117 }; | |
118 | |
119 DECLARE_LRECORD (specifier, struct Lisp_Specifier); | |
120 #define XSPECIFIER(x) XRECORD (x, specifier, struct Lisp_Specifier) | |
121 #define XSETSPECIFIER(x, p) XSETRECORD (x, p, specifier) | |
122 #define SPECIFIERP(x) RECORDP (x, specifier) | |
123 #define GC_SPECIFIERP(x) GC_RECORDP (x, specifier) | |
124 #define CHECK_SPECIFIER(x) CHECK_RECORD (x, specifier) | |
125 #define CONCHECK_SPECIFIER(x) CONCHECK_RECORD (x, specifier) | |
126 | |
127 /***** Calling a specifier method *****/ | |
128 | |
129 #define RAW_SPECMETH(sp, m) ((sp)->methods->m##_method) | |
130 #define HAS_SPECMETH_P(sp, m) (!!RAW_SPECMETH (sp, m)) | |
131 #define SPECMETH(sp, m, args) (((sp)->methods->m##_method) args) | |
132 | |
133 /* Call a void-returning specifier method, if it exists */ | |
134 #define MAYBE_SPECMETH(sp, m, args) \ | |
135 do { \ | |
136 struct Lisp_Specifier *_maybe_specmeth_sp = (sp); \ | |
137 if (HAS_SPECMETH_P (_maybe_specmeth_sp, m)) \ | |
138 SPECMETH (_maybe_specmeth_sp, m, args); \ | |
139 } while (0) | |
140 | |
141 MAC_DECLARE_EXTERN (struct Lisp_Specifier *, MTspecmeth_or_given) | |
142 | |
143 /* Call a specifier method, if it exists; otherwise return | |
144 the specified value */ | |
145 | |
146 #define SPECMETH_OR_GIVEN(sp, m, args, given) \ | |
147 MAC_BEGIN \ | |
148 MAC_DECLARE (struct Lisp_Specifier *, MTspecmeth_or_given, sp) \ | |
149 HAS_SPECMETH_P (MTspecmeth_or_given, m) ? \ | |
150 SPECMETH (MTspecmeth_or_given, m, args) : (given) \ | |
151 MAC_END | |
152 | |
153 /***** Defining new specifier types *****/ | |
154 | |
155 #define DECLARE_SPECIFIER_TYPE(type) \ | |
156 extern struct specifier_methods * type##_specifier_methods | |
157 | |
158 #define DEFINE_SPECIFIER_TYPE(type) \ | |
159 struct specifier_methods * type##_specifier_methods | |
160 | |
161 #define INITIALIZE_SPECIFIER_TYPE(type, obj_name, pred_sym) \ | |
162 do { \ | |
163 type##_specifier_methods = \ | |
164 malloc_type_and_zero (struct specifier_methods); \ | |
165 type##_specifier_methods->name = obj_name; \ | |
166 defsymbol (&type##_specifier_methods->predicate_symbol, \ | |
167 pred_sym); \ | |
168 add_entry_to_specifier_type_list (Q##type, \ | |
169 type##_specifier_methods); \ | |
170 } while (0) \ | |
171 | |
172 #define INITIALIZE_SPECIFIER_TYPE_WITH_DATA(type, obj_name, pred_sym) \ | |
173 do { \ | |
174 INITIALIZE_SPECIFIER_TYPE (type, obj_name, pred_sym); \ | |
175 type##_specifier_methods->extra_data_size = \ | |
176 sizeof (struct type##_specifier); \ | |
177 } while (0) | |
178 | |
179 /* Declare that specifier-type TYPE has method M; used in | |
180 initialization routines */ | |
181 #define SPECIFIER_HAS_METHOD(type, m) \ | |
182 (type##_specifier_methods->m##_method = type##_##m) | |
183 | |
184 /***** Macros for accessing specifier types *****/ | |
185 | |
186 #define SPECIFIER_TYPE_P(sp, type) \ | |
187 ((sp)->methods == type##_specifier_methods) | |
188 | |
189 #ifdef ERROR_CHECK_TYPECHECK | |
190 MAC_DECLARE_EXTERN (struct Lisp_Specifier *, MTspecifier_data) | |
191 # define SPECIFIER_TYPE_DATA(sp, type) \ | |
192 MAC_BEGIN \ | |
193 MAC_DECLARE (struct Lisp_Specifier *, MTspecifier_data, sp) \ | |
194 assert (SPECIFIER_TYPE_P (MTspecifier_data, type)) \ | |
195 MAC_SEP \ | |
196 (struct type##_specifier *) MTspecifier_data->data \ | |
197 MAC_END | |
198 #else | |
199 # define SPECIFIER_TYPE_DATA(sp, type) \ | |
200 ((struct type##_specifier *) (sp)->data) | |
201 #endif | |
202 | |
203 /* #### Need to create ERROR_CHECKING versions of these. */ | |
204 | |
205 #define XSPECIFIER_TYPE(x, type) XSPECIFIER (x) | |
206 #define XSETSPECIFIER_TYPE(x, p, type) XSETSPECIFIER (x, p) | |
207 #define SPECIFIER_TYPEP(x, type) \ | |
208 (SPECIFIERP (x) && SPECIFIER_TYPE_P (XSPECIFIER (x), type)) | |
209 #define CHECK_SPECIFIER_TYPE(x, type) \ | |
210 do { \ | |
211 CHECK_SPECIFIER (x); \ | |
212 if (!(SPECIFIERP (x) && SPECIFIER_TYPE_P (XSPECIFIER (x), \ | |
213 type))) \ | |
214 dead_wrong_type_argument \ | |
215 (type##_specifier_methods->predicate_symbol, x); \ | |
216 } while (0) | |
217 #define CONCHECK_SPECIFIER_TYPE(x, type) \ | |
218 do { \ | |
219 CONCHECK_SPECIFIER (x); \ | |
220 if (!(SPECIFIERP (x) && SPECIFIER_TYPE_P (XSPECIFIER (x), \ | |
221 type))) \ | |
222 x = wrong_type_argument \ | |
223 (type##_specifier_methods->predicate_symbol, x); \ | |
224 } while (0) | |
225 | |
226 /***** Miscellaneous structures *****/ | |
227 | |
228 enum spec_locale_type | |
229 { | |
230 LOCALE_GLOBAL, | |
231 LOCALE_DEVICE, | |
232 LOCALE_FRAME, | |
233 LOCALE_WINDOW, | |
234 LOCALE_BUFFER | |
235 }; | |
236 | |
237 enum spec_add_meth | |
238 { | |
239 SPEC_PREPEND, | |
240 SPEC_APPEND, | |
241 SPEC_REMOVE_TAG_SET_PREPEND, | |
242 SPEC_REMOVE_TAG_SET_APPEND, | |
243 SPEC_REMOVE_LOCALE, | |
244 SPEC_REMOVE_LOCALE_TYPE, | |
245 SPEC_REMOVE_ALL | |
246 }; | |
247 | |
248 struct specifier_caching | |
249 { | |
250 int offset_into_struct_window; | |
251 void (*value_changed_in_window) (Lisp_Object specifier, struct window *w, | |
252 Lisp_Object oldval); | |
253 int offset_into_struct_frame; | |
254 void (*value_changed_in_frame) (Lisp_Object specifier, struct frame *f, | |
255 Lisp_Object oldval); | |
256 }; | |
257 | |
258 extern Lisp_Object decode_locale (Lisp_Object locale); | |
259 extern Lisp_Object decode_locale_list (Lisp_Object locale); | |
260 extern Lisp_Object decode_domain (Lisp_Object domain); | |
261 extern enum spec_add_meth | |
262 decode_how_to_add_specification (Lisp_Object how_to_add); | |
263 extern Lisp_Object decode_specifier_tag_set (Lisp_Object tag_set); | |
264 | |
265 extern void add_entry_to_specifier_type_list (Lisp_Object symbol, | |
266 struct specifier_methods *meths); | |
267 extern void set_specifier_caching (Lisp_Object specifier, | |
268 int struct_window_offset, | |
269 void (*value_changed_in_window) | |
270 (Lisp_Object specifier, struct window *w, | |
271 Lisp_Object oldval), | |
272 int struct_frame_offset, | |
273 void (*value_changed_in_frame) | |
274 (Lisp_Object specifier, struct frame *f, | |
275 Lisp_Object oldval)); | |
276 extern void set_specifier_fallback (Lisp_Object specifier, | |
277 Lisp_Object fallback); | |
278 extern void recompute_all_cached_specifiers_in_window (struct window *w); | |
279 extern void recompute_all_cached_specifiers_in_frame (struct frame *f); | |
280 | |
281 extern void cleanup_specifiers (void); | |
282 extern void prune_specifiers (int (*obj_marked_p) (Lisp_Object)); | |
283 extern void setup_device_initial_specifier_tags (struct device *d); | |
284 void kill_specifier_buffer_locals (Lisp_Object buffer); | |
285 | |
286 DECLARE_SPECIFIER_TYPE (generic); | |
287 #define XGENERIC_SPECIFIER(x) XSPECIFIER_TYPE (x, generic) | |
288 #define XSETGENERIC_SPECIFIER(x, p) XSETSPECIFIER_TYPE (x, p, generic) | |
289 #define GENERIC_SPECIFIERP(x) SPECIFIER_TYPEP (x, generic) | |
290 #define CHECK_GENERIC_SPECIFIER(x) CHECK_SPECIFIER_TYPE (x, generic) | |
291 #define CONCHECK_GENERIC_SPECIFIER(x) CONCHECK_SPECIFIER_TYPE (x, generic) | |
292 | |
293 DECLARE_SPECIFIER_TYPE (integer); | |
294 #define XINTEGER_SPECIFIER(x) XSPECIFIER_TYPE (x, integer) | |
295 #define XSETINTEGER_SPECIFIER(x, p) XSETSPECIFIER_TYPE (x, p, integer) | |
296 #define INTEGER_SPECIFIERP(x) SPECIFIER_TYPEP (x, integer) | |
297 #define CHECK_INTEGER_SPECIFIER(x) CHECK_SPECIFIER_TYPE (x, integer) | |
298 #define CONCHECK_INTEGER_SPECIFIER(x) CONCHECK_SPECIFIER_TYPE (x, integer) | |
299 | |
300 DECLARE_SPECIFIER_TYPE (natnum); | |
301 #define XNATNUM_SPECIFIER(x) XSPECIFIER_TYPE (x, natnum) | |
302 #define XSETNATNUM_SPECIFIER(x, p) XSETSPECIFIER_TYPE (x, p, natnum) | |
303 #define NATNUM_SPECIFIERP(x) SPECIFIER_TYPEP (x, natnum) | |
304 #define CHECK_NATNUM_SPECIFIER(x) CHECK_SPECIFIER_TYPE (x, natnum) | |
305 #define CONCHECK_NATNUM_SPECIFIER(x) CONCHECK_SPECIFIER_TYPE (x, natnum) | |
306 | |
307 DECLARE_SPECIFIER_TYPE (boolean); | |
308 #define XBOOLEAN_SPECIFIER(x) XSPECIFIER_TYPE (x, boolean) | |
309 #define XSETBOOLEAN_SPECIFIER(x, p) XSETSPECIFIER_TYPE (x, p, boolean) | |
310 #define BOOLEAN_SPECIFIERP(x) SPECIFIER_TYPEP (x, boolean) | |
311 #define CHECK_BOOLEAN_SPECIFIER(x) CHECK_SPECIFIER_TYPE (x, boolean) | |
312 #define CONCHECK_BOOLEAN_SPECIFIER(x) CONCHECK_SPECIFIER_TYPE (x, boolean) | |
313 | |
314 #endif /* _XEMACS_SPECIFIER_H_ */ |