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_ */